Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do database connections get managed for Spring Data JPA repositories?

I have a question about how Spring Data repositories are handling the datasource connections. Assuming Spring Data repositories open and close the connection and the connection when the method executes, how does the transaction started by declaring @Transactional in my service layer span across multiple repository calls?

Who handles the database connections? The @Transactional annotation or the JPA repository?

like image 914
Magg Avatar asked Oct 17 '22 13:10

Magg


1 Answers

tl;dr

Ultimately it's the Spring JPA / Transaction infrastructure managing the connection via the thead-bound management of EntityManager instances. The scope of the transaction is controlled by @Transactional annotations in the user code but ultimately defaulted in Spring Data JPA's repository implementation. Connection acquisition is performed eagerly in case an OpenEntityManagerInViewFilter is used (enabled by default in Spring Boot 1.x and 2.x).

Details

SimpleJpaRepository is equipped with Spring's @Transactional annotations so that it will make sure it runs transactions in cases JPA requires them (e.g. to execute a call to EntityManager.persist(…) or ….merge(…)). Their default configuration makes sure, they automatically take part in transactions started at higher levels of abstraction. I.e. if you have a Spring component that's @Transactional itself, repositories will simply participate in the already running transaction:

@Component
class MyService {

  private final FirstRepository first;
  private final SecondRepository second;

  // Constructor omitted for brevity

  @Transactional
  void someMethod() {

     … = first.save(…);
     … = second.save(…);
  }
}

Both repositories participate in the transaction and a failure in one of them will roll back the entire transaction.

To achieve that, the JpaTransactionManager will use the transaction management API exposed by JPA's EntityManager to start a transaction and acquire a connection for the lifetime of the EntityManager instance. See JpaTransactionManager.doBegin(…) for details.

The role of an OpenEntityManagerInViewFilter or –Interceptor

Unless explicitly deactivated, Spring Boot 1.x and 2.x web applications run with an OpenEntityManagerInViewFilter deployed. Its used to create an EntityManager and thus acquire a connection pretty early and keep it around until very late in the request processing, namely after the view has been rendered. This has the effect of JPA lazy-loading being available to the view rendering but keeps the connection open for longer than if it was only needed for the actual transactional work.

That topic is quite a controversial one as its a tricky balance between developer convenience (the ability to traverse object relations to loaded lazily in the view rendering phase) at the risk of exactly that triggering expensive additional queries and keeping the resources in use for a longer time.

like image 52
Oliver Drotbohm Avatar answered Oct 29 '22 02:10

Oliver Drotbohm