32

I'm learning about how to create REST API with JPA and Hibernate and a MySQL database and I see this @Transactional annotation. Can someone explain what is the use of this annotation?

For example I have this simple DAO class:

@Repository
public class EmployeeDAOHibernateImpl implements EmployeeDAO {

    // define field for entitymanager
    private EntityManager entityManager;

    // set up constructor injection
    @Autowired
    public EmployeeDAOHibernateImpl(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    @Transactional
    public List<Employee> findAll() {

        // get the current hibernate session
        Session currentSession = entityManager.unwrap(Session.class);

        // create a query
        Query<Employee> theQuery = 
                currentSession.createQuery("from Employee", Employee.class);

        // execute query and get result list
        List<Employee> employees = theQuery.getResultList();

        // return the results
        return employees;
    }

}

You can see the @Transactional used for findAll() method, but if I delete this @Transactional I get the same output... then what is the use of this @Transactional?

  • 2
    Possible duplicate of [Spring - @Transactional - What happens in background?](https://stackoverflow.com/questions/1099025/spring-transactional-what-happens-in-background) – Sofo Gial Jan 23 '19 at 11:36
  • 2
    It's nothing to do with JPA ... FWIW. That is Spring –  Jan 23 '19 at 12:23

3 Answers3

85

@Transactional annotation is used when you want the certain method/class(=all methods inside) to be executed in a transaction.

Let's assume user A wants to transfer 100$ to user B. What happens is:

  1. We decrease A's account by 100$
  2. We add 100$ to B's account

Let's assume the exception is thrown after succeeding 1) and before executing 2). Now we would have some kind of inconsistency because A lost 100$ while B got nothing. Transactions means all or nothing. If there is an exception thrown somewhere in the method, changes are not persisted in the database. Something called rollback happens.

If you don't specify @Transactional, each DB call will be in a different transaction.

Pijotrek
  • 2,821
  • 1
  • 18
  • 32
  • 4
    a nice answer but an one thing should be added - in case of example code `@Transactional` is unnecessary, maybe it's "superstitious programming" where someone always adds @Transactional even if it has no effect "just in case" :) – kiedysktos Oct 01 '20 at 16:32
  • Thank you for the explanation it's simple and clear! – hakima maarouf May 29 '22 at 12:21
48

Generally the @Transactional annotation is written at the service level.

It is used to combine more than one writes on a database as a single atomic operation.

When somebody call the method annotated with @Transactional all or none of the writes on the database is executed.

In the case of read operations it is not useful and so it is in case of a single atomic write. You are using it in a single read (select) so adding or removing the @Transactional annotation has no impact.

Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56
  • 4
    In read operations it is useful if using Java Streams to place the select results... – viruskimera May 06 '19 at 00:57
  • worth to add that `@Transactional` should be used when there are multiple updates to entity that is in `persistent` state (managed by entity manager) , so `save()` could be not explicitly put in the code but setters are called on entity – kiedysktos Oct 01 '20 at 16:34
  • @viruskimera can you elaborate or provide some link? – kiedysktos Oct 01 '20 at 16:35
9

The class declares @Transactional on itself or its members, Spring creates a proxy that implements the same interface(s) as the class you’re annotating. In other words, Spring wraps the bean in the proxy and the bean itself has no knowledge of it.

A proxy provides a way for Spring to inject behaviors before, after, or around method calls into the object being proxied.

Internally, its the same as using a transaction advice (using AOP), where a proxy is created first and is invoked before/after the target bean’s method.

The generated proxy object is supplied with a TransactionInterceptor, which is created by Spring. So when the @Transactional method is called from client code, the TransactionInterceptor gets invoked first from the proxy object, which begins the transaction and eventually invokes the method on the target bean. When the invocation finishes, the TransactionInterceptor commits/rolls back the transaction accordingly

Sai prateek
  • 11,842
  • 9
  • 51
  • 66