1

I have got stuck a number of times asking myself why wasn't my code persisting the data in the database. I mean, I have got my simple method annotated with @Transactional and everyting seems to go fine, no problems. After trying to discover the reason for some time I will eventually remember that I am actually calling my transactional method from the inside of the same class, and hence spring will promptly ignore the annotation. It happend to me that in those cases I was marking the method as transactional on my @Controller layer, which seemed to limit code re-usability. So, I have two questions in regard of this problem:

  • On which level of the spring architecture is the @Transactional best placed (@Controller, @Service etc..)?
  • Why exactly does spring ignore the annotation when the annotated method is called from the inside of the class?
NiVeR
  • 9,644
  • 4
  • 30
  • 35
  • 1
    https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#tx-decl-explained – JB Nizet Sep 27 '17 at 21:21

2 Answers2

2

On which level of the spring architecture is the @Transactional best placed (@Controller, @Service etc..)?

Based on my experience, it is best placed on service layer. You can add it in other layers also but just be consistent about it. Because if you add any more annotations based on this '@Transactional' annotation, it's behaviour should be same all across your application.

Why exactly does spring ignore the annotation when the annotated method is called from the inside of the class?

You can read about how Spring AOP works on based on proxies. Here are your references -

Spring nested transactions

@Transactional method calling another method without @Transactional anotation?

asg
  • 2,248
  • 3
  • 18
  • 26
1

The spring documentation is a very good source for explaining this. At its most basic, when you are using spring with annotations like transactional, when spring injects an object it is actually injecting a proxy to that object. This allows it to intercept method calls and do stuff like manage transactions. When you instantiate an object yourself or make a call to another instance method within the same class you are not calling through a spring proxy and it will not be able to manage that call.

As for where the Transactional annotation should be placed this is dependent on your codebase and opinion on project structure. Personally, I place them as high up the call stack as logically makes sense.

Deadron
  • 5,135
  • 1
  • 16
  • 27