Search code examples
springspring-boothikaricp

spring boot connection pool with long running requests


When a spring boot request starts, it obtains a connection from the pool. My question is - is this connection remains tied to the request thread (even if it is not executing any query) and only returned to the pool when request completes?

For example, if I'm doing something like:

  1. Request starts
  2. Execute a query (20ms)
  3. Call external http service (1500ms)
  4. Request completes

Would the connection obtained by this request thread remain occupied with the thread (and not available to other requests) for 20ms or 1520ms?

PS: I'm using Spring Boot 2.0 with HikariCP and I'm not using @Transactional.

Thanks.


Solution

  • If you have Spring MVC on your classpath, Spring will configure an instance of OpenEntityManagerInViewInterceptor automatically (in org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.JpaWebConfiguration), unless you configure spring.jpa.open-in-view to false. This interceptor will open an instance of EntityManager and bind it to the TransactionSynchronizationManager for the whole duration of the request.

    What that means is that at the first use of a repository query, it will borrow a connection from the pool and keep it until the end of the request when the EntityManager is closed by the interceptor. It's the EntityManager's responsibility to return the connection to the pool. So, in that case, the connection will be borrowed for 1520ms in your example.

    If you disable the spring.jpa.open-in-view option, a connection will be borrowed and returned at each use of a repository query given you don't use any explicit transaction. While this may look better, you have to keep in mind that managed instances of your entities will need to be reattached systematically on each persist operation so it may be costly. You will also loose the benefits of the EntityManager caching. To avoid this, use transactions to read/modify/persist your entities and avoid reattaching.

    Finally, keep in mind that if you disable spring.jpa.open-in-view, since you don't have an EntityManager around for the duration of the request, you will need to make sure your lazy loaded relations are loaded inside a transaction otherwise you'll get the dreaded LazyInitializationException.