@Transactional method calling another method without @Transactional anotation?

JavaSpringSpring TransactionsTransactional

Java Problem Overview


I've seen a method in a Service class that was marked as @Transactional, but it was also calling some other methods in that same class which were not marked as @Transactional.

Does it mean that the call to separate methods are causing the application to open separate connections to DB or suspend the parent transaction, etc?

What's the default behavior for a method without any annotations which is called by another method with @Transactional annotation?

Java Solutions


Solution 1 - Java

When you call a method without @Transactional within a transaction block, the parent transaction will continue to the new method. It will use the same connection from the parent method (with @Transactional) and any exception caused in the called method (without @Transactional) will cause the transaction to rollback as configured in the transaction definition.

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. But if you call a method with a transaction definition from another method with a transaction definition, and they belong to different Spring Beans, then the code in the called method will follow its own transaction definitions.

You can find more details in the section Declarative transaction management of spring transaction documentation.

Spring declarative transaction model uses AOP proxy, so the AOP proxy is responsible for transactions creation. The AOP proxy will be active only if the called method belong to a different Spring Bean than the caller one.

Solution 2 - Java

  • Does that mean the call to separate methods are causing the application to open separate connections to DB or suspend the parent transaction, etc?

That depends on a propagation level. Here are all the possible level values.

For example in case a propagation level is NESTED a current transaction will "suspend" and a new transaction will be created ( note: actual creation of a nested transaction will only work on specific transaction managers )

  • What's the default behavior for a method without any annotations that is called by another method with @Transactional annotation?

The default propagation level ( what you call "behavior" ) is REQUIRED. In case an "inner" method is called that has a @Transactional annotation on it ( or transacted declaratively via XML ), it will execute within the same transaction, e.g. "nothing new" is created.

Solution 3 - Java

@Transactional marks the transaction boundary (begin/end) but the transaction itself is bound to the thread. Once a transaction starts it propagates across method calls until the original method returns and the transaction commits/rolls back.

If another method is called that has a @Transactional annotation then the propagation depends on the propagation attribute of that annotation.

Solution 4 - Java

The inner method will affect the outer method if the inner method is not annotated with @Transactional.

In case inner method is also annotated with @Transactional with REQUIRES_NEW, following will happen.

...
@Autowired
private TestDAO testDAO;

@Autowired
private SomeBean someBean;

@Override
@Transactional(propagation=Propagation.REQUIRED)
public void outerMethod(User user) {
  testDAO.insertUser(user);
  try{
    someBean.innerMethod();
  } catch(RuntimeException e){
    // handle exception
  }
}


@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void innerMethod() {
  throw new RuntimeException("Rollback this transaction!");
}

The inner method is annotated with REQUIRES_NEW and throws a RuntimeException so it will set its transaction to rollback but WILL NOT EFFECT the outer transaction. The outer transaction is PAUSED when the inner transaction starts and then RESUMES AFTER the inner transaction is concluded. They run independently of each other so the outer transaction MAY commit successfully.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongoeView Question on Stackoverflow
Solution 1 - JavaArun P JohnyView Answer on Stackoverflow
Solution 2 - JavatolitiusView Answer on Stackoverflow
Solution 3 - JavasourcedelicaView Answer on Stackoverflow
Solution 4 - Javasaran3hView Answer on Stackoverflow