@Transactional
public class UserServiceImpl implements UserService {
...................
public void method1(){
try{
In case 1 @Transactional is applied to every public individual method. Private and Protected methods are Ignored by Spring.
Spring applies the class-level annotation to all public methods of this class that we did not annotate with @Transactional. However, if we put the annotation on a private or protected method, Spring will ignore it without an error.
In case 2 @Transactional is only applied to method2(), not on method1()
Case 1: - Invoking method1() -> a transaction is started. When method1() calls method2() no new transaction is started, because there is already one
Case 2: - Invoking method1() -> no transaction is started. When method1() calls method2() NO new transaction is started. This is because @Transactional does not work when calling a method from within the same class. It would work if you would call method2() from another class.
From the spring reference manual:
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. @PostConstruct.
@Transactional
on a class applies to each method on the service. It is a shortcut. Typically, you can set @Transactional(readOnly = true)
on a service class, if you know that all methods will access the repository layer. You can then override the behavior with @Transactional
on methods performing changes in your model. Performance issues between 1) and 2) are not known.
Quoting from here
The Spring team's recommendation is that you only annotate concrete classes with the @Transactional annotation, as opposed to annotating interfaces.
Since this mechanism is based on proxies, only 'external' method calls coming in through the proxy will be intercepted. This means that 'self-invocation', i.e. a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with @Transactional!
Suppose you have the following class:
@Transactional(readOnly = true)
public class DefaultFooService implements FooService {
public Foo getFoo(String fooName) {
// do something
}
// these settings have precedence for this method
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void updateFoo(Foo foo) {
// do something
}
}
The @Transactional
annotation on the class level will be applied to every method in the class.
However, when a method is annotated with @Transactional
(like, updateFoo(Foo foo)
) this will take precedence over the transactional settings defined at the class level.
More info: