How does @Transactional influence current session in Hibernate?

database, hibernate, java, spring

Solution

In Spring, there is a one-to-one correspondence between the business transaction demarcated by `@Transactional`, and the hibernate `Session`.

That is, when a business transaction is begun by invoking a `@Transactional` method, the hibernate session is created (a TransactionManager may delay the actual creation until the session is first used). Once that method completes, the business transaction is committed or rolled back, which closes the hibernate session.

In your case, this means that invoking a DAO method will begin a new transaction (unless a transaction is already in progress), and exiting the DAO method will end it, which closes the hibernate session, which also flushes it, and commits or rolls back the corresponding hibernate transaction, which in turn commits or rolls back the corresponding JDBC transaction.

As for this being typical use, the hibernate documentation calls this the session-per-operation anti pattern. Likewise, all examples of `@Transactional` in the spring reference manual are put on business service methods (or classes), not repositories.

Problem

This is a typical setup used in most DAO: ``` @Transactional @Repository public class DAO { @Autowired SessionFactory sessionFactory; public void save(Entity o) { sessionFactory.getCurrentSession().save(o); } public Entity load(int id) { return (Entity)sessionFactory.getCurrentSession().get(Entity.class, id); } } ``` I see only `getCurrentSession()` called, no `openSession` or `close`. So when I return the entity from `load` it's not in session, lazy collections cant be loaded. Similarily, save seems to always flush! Does the `@Transactional` annotation from spring do the magic of opening and closing sessions AND transactions all by itself?

Original source

Related problems