Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does @Transactional influence current session in Hibernate?

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?

like image 635
Binders Lachel Avatar asked Jul 12 '14 07:07

Binders Lachel


People also ask

What does @transactional do in hibernate?

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.

What does the @transactional annotation do?

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.

How does Spring @transactional really work?

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.

What is the function of @transactional at class level?

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.


2 Answers

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.

like image 174
meriton Avatar answered Oct 26 '22 03:10

meriton


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 @Transactionalcontext, 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.

like image 35
Bhushan Avatar answered Oct 26 '22 02:10

Bhushan