In my java process, I connect to MySql using the following spring configuration:
@Configuration @EnableTransactionManagement @PropertySources({ @PropertySource("classpath:/myProperties1.properties"), @PropertySource("classpath:/myProperties2.properties") }) public class MyConfiguration { @Autowired protected Environment env; /** * @return EntityManagerFactory for use with Hibernate JPA provider */ @Bean(destroyMethod = "destroy") public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); em.setJpaVendorAdapter(jpaVendorAdapter()); em.setPersistenceUnitManager(persistenceUnitManager()); return em; } /** * * @return jpaVendorAdapter that works in conjunction with the * persistence.xml */ @Bean public JpaVendorAdapter jpaVendorAdapter() { HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); vendorAdapter.setDatabase(Database.valueOf(env.getProperty("jpa.database"))); vendorAdapter.setDatabasePlatform(env.getProperty("jpa.dialect")); vendorAdapter.setGenerateDdl(env.getProperty("jpa.generateDdl", Boolean.class, false)); vendorAdapter.setShowSql(env.getProperty("jpa.showSql", Boolean.class, false)); return vendorAdapter; } @Bean public PersistenceUnitManager persistenceUnitManager() { DefaultPersistenceUnitManager pum = new DefaultPersistenceUnitManager(); pum.setPackagesToScan("com.app.dal"); pum.setDefaultPersistenceUnitName("my-pu"); pum.setPersistenceXmlLocations("classpath:/META-INF/persistence.xml"); pum.setDefaultDataSource(dataSource()); return pum; } @Bean(destroyMethod = "close") public DataSource dataSource() { Properties dsProps = new Properties(); dsProps.put("driverClassName", env.getProperty("hikari.driverClassName")); dsProps.put("username", env.getProperty("hikari.username")); dsProps.put("password", env.getProperty("hikari.password")); dsProps.put("jdbcUrl", env.getProperty("hikari.source.data.jdbcUrl")); dsProps.put("connectionTimeout", env.getProperty("hikari.connectionTimeout", Integer.class)); dsProps.put("idleTimeout", env.getProperty("hikari.idleTimeout", Integer.class)); dsProps.put("maxLifetime", env.getProperty("hikari.maxLifetime", Integer.class)); dsProps.put("maximumPoolSize", env.getProperty("hikari.maximumPoolSize.rtb.source", Integer.class)); dsProps.put("leakDetectionThreshold", env.getProperty("hikari.leakDetectionThreshold", Integer.class)); dsProps.put("jdbc4ConnectionTest", env.getProperty("hikari.jdbc4ConnectionTest", Boolean.class)); HikariConfig config = new HikariConfig(dsProps); HikariDataSource ds = new HikariDataSource(config); return ds; } @Bean(name = "sourceTxMgr") public PlatformTransactionManager sourceDatatransactionManager() { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setPersistenceUnitName("my-pu"); transactionManager.setDataSource(dataSource()); return transactionManager; } @Bean public PersistencyManager persistencyManager() { return new JpaPersistencyManager(); } @Bean public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { return new PersistenceExceptionTranslationPostProcessor(); } }
Entity-Manager is introduced at the level of access to this container:
@PersistenceContext(type = PersistenceContextType.TRANSACTION, unitName = "my-pu") private EntityManager myEntityManager;
And my public business logic methods are annotated with @Transactional annotation.
As far as I understand, the container is responsible for the fact that the manager entity returns connections to the pool (in my case HikariCP ) after the transaction is completed, but I did not find the official documentation describing connection management. Can someone explain this to me or provide a good link that can explain exactly when the connections are returned to the pool when using this configuration?
UPDATE:
The best related information I could find so far ( taken here ):
The persistence context proxy that implements EntityManager is not the only component required to perform declarative transaction management. In fact, three separate components are needed:
EntityManager Proxy Transactional Aspect Transaction Manager Let's move on to each of them and see how they interact.
Transactional aspect
The Transactional Aspect is an “around” aspect that is invoked both before and after the annotated business method. The specific class for implementing the aspect is the TransactionInterceptor.
The transactional aspect has two main responsibilities:
At the “before” point, this aspect provides a reference point for determining whether the business method to be invoked should be launched as part of the current database transaction or if a new separate transaction needs to be started.
At the “after” point, the aspect should decide whether to commit the transaction, rollback, or leave it on the go.
At the time “before”, Transactional Aspect itself does not contain decision logic, the decision to start a new transaction is delegated to the transaction manager, if necessary.
Transaction manager
The transaction manager should provide an answer to two questions:
should a new Entity Manager be created? should a new database transaction be started? This must be resolved when the Transactional Aspect "before" logic is invoked. The transaction manager will make a decision based on:
the fact that one transaction is already ongoing or not the attribute of the distribution of the transaction method (for example, REQUIRES_NEW always starts a new transaction) If the transaction manager decides to create a new transaction, it will:
create a new object manager bind the object manager to the current thread grab the connection from the DB connection pool bind the connection to the current thread Object manager and the connection are bound to the current thread using ThreadLocal variables.
They are stored in the stream during the execution of the transaction, and before the transaction manager they clear them when they are no longer needed.
Any parts of the program that need a current manager or entity connection can extract them from the stream. One software component that does exactly this is the EntityManager proxy.