6

Trying to collect and understand the main points of @Transactional annotation and crossed one point. So, the main things that we need to keep in mind when using Transactional annotation are:

  1. Transactional annotation can be applied only to public methods [according to Does Spring @Transactional attribute work on a private method?
  2. Transactional annotation should be applied to the concrete classes instead of interfaces [according to Where should I put @Transactional annotation: at an interface definition or at an implementing class?
  3. Transactional annotation should be applied on the Service level [according to Spring @Transactional Annotation Best Practice
  4. If you want to exclude some public method from being annotated with Transactional when whole class is annotated you can use some propagation strategies [according to Transactional annotation on whole class + excluding a single method

Unfortunately I didn't find the answer to the question: Where it is better to put Transactional annotation - to the class or method? We can consider different situations, but mostly i am interested in the one when we have several methods which must have this annotation and some which don't.

Plus, maybe you would like to add some points to this list, that would be really great.

Community
  • 1
  • 1
Rufi
  • 2,529
  • 1
  • 20
  • 41
  • 2
    1 is no longer true, and hasn't been for some time. If you use Spring's weaving support (compile time or load time) the the annotation can be on _any_ method. – Boris the Spider Mar 13 '15 at 08:35
  • Well if some of your methods don't need that annotation that means you don't need a transaction at all if I am getting you right. So why should you then open a transaction throught annotation if you're declaring it on your class? I would recommend just write that annotation on all methods which need a transaction. – Jan Mar 13 '15 at 09:48
  • @BoristheSpider, that's an interesting fact, thank you. – Rufi Mar 13 '15 at 14:17
  • @Jan, that's the point. If I have a lot of methods which need to be Transactional I feel that it is kind of duplicated code if I put my transactional annotation to all of these methods instead of the class. And I am just guessing if it is bad to put it to the class even though some other methods don't need Transactional. – Rufi Mar 13 '15 at 14:22
  • Code duplication in this case doesn't matter. IMHO in your case transactions should not be seen as a cross cutting concern, since sometimes they are not needed. In a more general sense, I would always avoid transaction annotation on class level, and define method that do what u need to do in your transaction, this will favour a clear separations of concerns and testability – Raffaele Nov 02 '18 at 16:03

2 Answers2

3

Here is a list of pros and (implicitly) cons I can think of.

Pro Method Level:

  • Easy to read: You look at a method and can tell that it is transactional without having to look at the class, its implemented interfaces or super-classes.
  • Explicit: The annotation clearly tells you that the method is meant to be transactional. It is not just transactional because all methods in the class are transactional.
  • Less unintended merging of (otherwise) independent transactions: If you call multiple transactional methods from a method that is (implicitly) transactional, then the outer transaction defines the whole transaction (unless the propagation settings are like REQUIRES_NEW or so). While this is in many cases no problem, I have seen projects getting into serious trouble due to this in the long run. Especially when it comes to pessimistic locking, it is crucial to keep transactions as independent and small as possible, so transactions need only few locks and the locks are released as soon as possible.

Pro Class Level:

  • Less repetitive: If you put the annotation on the class level, you do not have to annotate each and every transactional method. Some people argue that putting the annotation on each transactional method is against the DRY principle. However, IMHO, if this is against the DRY principle, then Java's private/protected/public modifiers are, too.
yamass
  • 765
  • 5
  • 14
2

In my opinion it is better to mark each method with @Transactional annotation separately (to indicate that this method is updating something) instead of marking whole class. This will produce more code and can be redundant in some cases but imagin that you have for example 10 methods in your service. Nine of those methods are updating something and one is only reading. Your code is using ORM (for example Hibernate) and you have some objects managed by Hibernate in your method. During adding new logic you accidentaly changed one field in object managed by Hibernate. In this case hibernate will fire update sql insturction in method which should only read. It may produce bug which is hard to find.

Patryk kowalski
  • 313
  • 2
  • 5
  • 18