Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Transactional method called from another method doesn't obtain a transaction

In Spring, a method that is annotated with @Transactional will obtain a new transaction if there isn't one already, but I noticed that a transactional method does not obtain any transaction if it is called from a non-transactional one. Here's the code.

@Component public class FooDao {     private EntityManager entityManager;      @PersistenceContext     protected void setEntityManager(EntityManager entityManager) {         this.entityManager = entityManager;     }      @Transactional     public Object save(Object bean) {         return this.entityManager.merge(bean);     }      public Object saveWrap(Object bean) {         return save(bean);     } }  @Component public class FooService {     private FooDao fooDao;      public void save(Object bean) {         this.fooDao.saveWrap(bean); // doesn't work.         this.fooDao.save(bean); // works     } } 

saveWrap() is a regular method that calls save() which is transactional, but saveWrap() won't persist any changes.

I'm using Spring 3 and Hibernate 3. What am I doing wrong here? Thanks.

like image 822
Tom Tucker Avatar asked Feb 24 '11 19:02

Tom Tucker


People also ask

What happens if a method annotated with @transactional calls another method annotated with transactional?

If you call a method with a @Transactional annotation from a method with @Transactional belonging to the same Spring Bean , then the called methods transactional behavior will not have any impact on the transaction.

What happens if one @transactional annotated method is calling another @transactional annotated method on the same object instance?

1 Answer. Show activity on this post. If you call method2() from method1() within the same class, the @Transactional annotation of the second method will not have any effect because it is not called through proxy, but directly.

How do you check if @transactional is working?

You can check if transaction is active using TransactionSynchronizationManager. isActualTransactionActive() . But you should call it before a service method executing. TransactionStatus status = TransactionAspectSupport.

Does @transactional work on private methods?

The answer your question is no - @Transactional will have no effect if used to annotate private methods. The proxy generator will ignore them. When using proxies, you should apply the @Transactional annotation only to methods with public visibility.


2 Answers

It is one of the limitations of Springs AOP. Because the dao bean is in fact a proxy when it is created by spring, it means that calling a method from within the same class will not call the advice (which is the transaction). The same goes for any other pointcut

like image 69
Clinton Bosch Avatar answered Sep 21 '22 00:09

Clinton Bosch


Yes, this is expected behaviour. @Transactional tells spring to create a proxy around the object. The proxy intercepts calls to the object from other objects. The proxy does not intercept calls within the object.

If you want to make this work, add @Transactional on the method that is invoked from "outside".

like image 30
Bozho Avatar answered Sep 23 '22 00:09

Bozho