连接何时被返回到Spring JPA(Hibernate)实体管理器的连接池中?
连接何时被返回到Spring JPA(Hibernate)实体管理器的连接池中?
在我的Java进程中,我使用以下的Spring配置连接到MySQL:
@Configuration @EnableTransactionManagement @PropertySources({ @PropertySource("classpath:/myProperties1.properties"), @PropertySource("classpath:/myProperties2.properties") }) public class MyConfiguration { @Autowired protected Environment env; @Bean(destroyMethod = "destroy") public LocalContainerEntityManagerFactoryBean entityManagerFactory() { // 省略代码... } @Bean public JpaVendorAdapter jpaVendorAdapter() { // 省略代码... } @Bean public PersistenceUnitManager persistenceUnitManager() { // 省略代码... } @Bean(destroyMethod = "close") public DataSource dataSource() { // 省略代码... } @Bean(name = "sourceTxMgr") public PlatformTransactionManager sourceDatatransactionManager() { // 省略代码... } @Bean public PersistencyManager persistencyManager() { // 省略代码... } @Bean public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { // 省略代码... } }
实体管理器通过容器注入到数据访问层中:
@PersistenceContext(type = PersistenceContextType.TRANSACTION, unitName = "my-pu") private EntityManager myEntityManager;
我的公共业务逻辑方法都使用`@Transactional`注解进行标注。
据我所理解,容器负责确保在事务完成后,实体管理器将连接返回到连接池(在我这里是HikariCP),但我没有找到任何官方文档来描述连接是如何管理的。有人能解释给我听,或者能提供一个能解释在使用这样的配置时连接何时被返回到连接池的好的参考资料吗?
强调更新:
到目前为止,我能找到的最相关的信息是从这里摘录的(取自这里):
持久化上下文代理实现了EntityManager并不是使声明式事务管理工作所必需的唯一组件。实际上,需要三个独立的组件:
实体管理器代理本身
事务切面
事务管理器
让我们逐个讨论它们,并看看它们如何相互作用。
事务切面
事务切面是一个环绕切面,会在注解的业务方法之前和之后被调用。实现该切面的具体类是TransactionInterceptor。
事务切面有两个主要的职责:
在“之前”时刻,该切面提供了一个挂钩点,用于确定即将调用的业务方法是否应在一个正在进行的数据库事务范围内运行,或者是否应启动一个新的单独的事务。
在“之后”时刻,该切面需要决定事务是提交、回滚还是保持运行。
在“之前”时刻,事务切面本身不包含任何决策逻辑,是否需要启动新事务的决策被委托给了事务管理器。
事务管理器
事务管理器需要回答两个问题:
是否应创建一个新的实体管理器?
是否应启动一个新的数据库事务?
这需要在调用事务切面的“之前”逻辑时做出决策。事务管理器将根据以下因素做出决策:
当前是否已经存在一个事务
事务方法的传播属性(例如,REQUIRES_NEW始终启动一个新事务)
如果事务管理器决定创建一个新事务,那么它将:
创建一个新的实体管理器
将实体管理器绑定到当前线程
从数据库连接池中获取一个连接
将连接绑定到当前线程
实体管理器和连接都使用ThreadLocal变量绑定到当前线程。
它们在事务运行时存储在线程中,当不再需要时,由事务管理器清理。
需要当前实体管理器或连接的程序的任何部分都可以从线程中检索它们。一个正好这样做的程序组件是实体管理器代理。