Repaso
Español

Why might @Transactional NOT work in this code?

@Service
public class ReportService {

    public void generate() {
        saveAll();               // call inside the same class
    }

    @Transactional
    public void saveAll() { ... }
}

Options

  1. Because the method is public and it must be private
  2. Transactions use a proxy; a call within the class skips it (Correct option)
  3. Because @Transactional only ever works on interfaces
  4. Because the method has no parameters declared in it

Answer

Because Spring applies transactions through a proxy, and a call from another method of the same class (self-invocation) bypasses the proxy

Why

Spring does not change your class. It wraps the bean in a proxy object that starts and commits the transaction around the call.

When an outside class calls reportService.saveAll(), it goes through the proxy and works. But when generate() calls saveAll() inside the same object, it is a normal Java call on this, so the proxy is skipped and there is no transaction.

Same problem with private or final methods. Fix: move the method to another bean, or put @Transactional on the method called from outside.

Remember

Self-invocation and private methods bypass Spring's proxy.

Key terms

Practice this question in Repaso