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?
The @Transactional annotation is the metadata that specifies the semantics of the transactions on a method. We have two ways to rollback a transaction: declarative and programmatic. In the declarative approach, we annotate the methods with the @Transactional annotation.
Transactional annotation provides the application the ability to declaratively control transaction boundaries on CDI managed beans, as well as classes defined as managed beans by the Java EE specification, at both the class and method level where method level annotations override those at the class level.
So when you annotate a method with @Transactional , Spring dynamically creates a proxy that implements the same interface(s) as the class you're annotating. And when clients make calls into your object, the calls are intercepted and the behaviors injected via the proxy mechanism.
Annotation Type Transactional. Describes a transaction attribute on an individual method or on a class. When this annotation is declared at the class level, it applies as a default to all methods of the declaring class and its subclasses.
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.
Spring provide transaction advice to beans which are annotated with @Transactional. Spring transaction provides support for following six attributes which determines the behavior of the transaction
1.isolation , 2.no-rollback-for, 3.propagation, 4.read-only, 5.rollback-for, 6.timeout.
@Transactional
can start new transaction or can join existing transactional context based its propagation attribute value.
In @Transactional
context, getCurrentSession()
method creates new Session object if it does not exist or returns Session which is attached to current transaction. OpenSession() method always creates new session. @Transactional
helps you to extend scope of Session
.
Session is open first time when getCurrentSession() is executed and it is closed when transaction ends and it is flushed before transaction commits.
In Spring, If we use getCurrentSession()
in non-transactional context we get an exception.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With