Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling @Transactional method from non-transactional method in Spring 4.3 [duplicate]

I have the following code:

@Service
public class ItemService {
    ...

    public void addItems(@Nonnull DocumentDTO dto) throws Exception {
        // some code that takes some time to process
        ...

        addItems(dto.getDocId(), items);
    }

    @Transactional
    public void addItems(long docId, @Nonnull List<Item> items) {
        itemDao.addItems(docId, items);
    }
}

The first method is not @Transactional and it calls the second one with @Transactional. SonarLint tool states that "Methods should not call same-class methods with incompatible "@Transactional" values" (https://rules.sonarsource.com/java/RSPEC-2229)

But this code works correctly in Spring 4.3.20. Is this rule actual for Spring 4.3.20?

P.S. Interesting, if I make the second method as package-private, the SonarLint warning disappears... Why?

like image 944
serg kunz Avatar asked Feb 07 '19 05:02

serg kunz


People also ask

What happens if one @transactional annotated method is calling another @transactional annotated method on the same object instance?

1 Answer. Show activity on this post. If you call method2() from method1() within the same class, the @Transactional annotation of the second method will not have any effect because it is not called through proxy, but directly.

What happens if a method annotated with @transactional calls another method annotated with transactional?

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.

Can we use @transactional on private methods?

The answer your question is no - @Transactional will have no effect if used to annotate private methods. The proxy generator will ignore them. When using proxies, you should apply the @Transactional annotation only to methods with public visibility.

When a caller object calls a method annotated with @transactional is it invoked immediately?

Answer 2: Yes, this is expected behaviour.


1 Answers

But this code works correctly in Spring 4.3.20. Is this rule actual for Spring 4.3.20?

Yes. SonarLint is correct. Self-invocation cannot make @Transactional to take effect. It does not change even in Spring 5. That is how Spring AOP works (refer to docs). Your codes works most probably because you start another transaction inside itemDao (May be you have another @Transactional marked on ItemDao#addItems()).

if I make the second method as package-private, the SonarLint warning disappears... Why?

Don't know why. Maybe it is a bug. As mentioned in this rule , it should give you warning when mark @Transactional in private method.

like image 79
Ken Chan Avatar answered Sep 21 '22 23:09

Ken Chan