131

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?

Mikhail Kholodkov
  • 23,642
  • 17
  • 61
  • 78
goe
  • 1,311
  • 2
  • 9
  • 3

4 Answers4

168

When you call a method without @Transactional within a transaction block, the parent transaction will propagate 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 method's 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 Management documentation.

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

Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
  • is that the spring default behavior ? – goe Jun 03 '11 at 03:18
  • Yes. It is the default behavior. – Arun P Johny Jun 03 '11 at 03:20
  • @Arun There is one more dimension to that which is transaction propagation attribute. In [`@Transactional`](http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/transaction/annotation/Transactional.html) you can specify propagation attribute that is enumeration value of type [`@Propagation`](http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/transaction/annotation/Propagation.html). – Tomasz Błachowicz Jun 03 '11 at 12:43
  • 2
    @Tomasz Yes. But it should also be mentioned that changing transaction propagation on a method that is called from another @Transactional method will have no effect. – Fil Jun 03 '11 at 17:13
  • 1
    @Tomasz, That was what I meant by saying `will follow the transaction definitions given in the called method`. But if the call is comes from the same object instance it will not have any effect since the call will not propagate through the aop proxies which are responsible for the transaction maintenance. – Arun P Johny Jun 04 '11 at 06:29
  • 8
    @Filip, That is not completely correct, If you call a method with a `@Transactional` definition from a different object/instance then even though the calling method have a different `@Transactional` attributes, the called method will follow the it own transaction definition. – Arun P Johny Jun 04 '11 at 06:33
  • @Arun You're right, I was strictly speaking about self-invocation where the container isn't involved in serving up a proxy. – Fil Jun 04 '11 at 12:11
  • ".. will not have any impact on the transaction." - what does that mean? the inner method with `@transactional` is executed in same transaction as parent with `@transactional` method correct? – brain storm May 24 '18 at 21:01
  • so does it means that if I call a transactional method from the same instance's method that has no transactional annotation, the transaction will not working? I think due to spring aop it will not working since it cannot get the proxy call. – Surely Sep 25 '18 at 09:36
  • But default propogation is `REQUIRED Support a current transaction, create a new one if none exists.` – Alex78191 Oct 07 '19 at 17:16
  • 1
    @ArunPJohny what does it mean: "within the same instance"? Eg. I have parent method with Transactional annotation and within this method I call another method with Transactional from another service... When in child method something woll go wrong with exception, then I want to rollback everything... – Matley Apr 18 '21 at 21:34
26
  • 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.

tolitius
  • 22,149
  • 6
  • 70
  • 81
  • What about subcalls of NOT_SUPPORTED which dont have any annotation? Does it inherit NOT_Supported or did they open a new transaction as REQURED is the default? For example: f1.call(){ f2() } with the annotation NOT_SUPPORTED for f1 and non for f2. – Dave Jul 07 '17 at 21:07
13

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

Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
sourcedelica
  • 23,940
  • 7
  • 66
  • 74
  • 1
    The 3 answers conflict with each other in some degree, not sure which is more accurate. – Eric Mar 27 '19 at 09:52
  • 1
    @EricWang Just wanted to share that I tested out this scenario today and the answer by [Arun P Johny](https://stackoverflow.com/questions/6222600/transactional-method-calling-another-method-without-transactional-anotation#6222624) *(with comments)* is the most accurate for this scenario of **internal** invocations. – Vinay Vissh Feb 25 '20 at 08:19
8

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

In case the inner method is also annotated with @Transactional with Propagation.REQUIRES_NEW, the 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.

Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
saran3h
  • 12,353
  • 4
  • 42
  • 54
  • 9
    To clarify for beginners, I'm pretty sure innerMethod() needs to be on a different bean (aka Spring-managed java Object) than outerMethod(). If they are both on the same bean, I don't think the innerMethod will actually use the Transactional behavior declared in its annotation. Rather it will use what is declared in the outerMethod() declaration. This is because of how Spring handles AOP, which is used for it's @Transactional annotations (https://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#tx-decl-explained) – johnsimer Aug 23 '20 at 21:33