Spring Boot 中的 PersistenceContext 生命周期

Posted

技术标签:

【中文标题】Spring Boot 中的 PersistenceContext 生命周期【英文标题】:PersistenceContext lifecycle in Spring Boot 【发布时间】:2021-06-14 01:03:57 【问题描述】:

我试图理解 Spring Boot 应用程序中的持久性上下文是如何工作的。我使用 Spring Data、Hibernate 和 Hikari。

我不知道PersistenceContext 何时创建以及何时关闭。根据几篇文章,例如https://www.baeldung.com/jpa-hibernate-persistence-context 或https://dzone.com/articles/how-does-spring-transactional 这一PersistenceContext 生命周期与EntityManager 生命周期相同。所以我想知道,当EntityManager 实际创建时,它关闭时更重要,最重要的是它在事务结束时关闭。根据我的发现,枚举PersistenceContextType.java 决定了我将拥有什么PersistenceContextPersistenceContextType.TRANSACTION 应该是默认的,应该导致 SharedEntityManagerInvocationHandler 被用作 EntityManager 的实现并且应该在事务结束时关闭,而 PersistenceContextType.EXTENDED 应该比事务更有效并且应该导致 @正在使用 987654333@。所以我尝试通过调试来证明它,我发现了以下内容。

    PersistenceContextType.EXTENDED 没有在任何地方进行评估。 PersistenceAnnotationBeanPostProcessor.java 有一些用法,但是在我的集成测试中断点从未停止过。

    有时会调用SharedEntityManagerInvocationHandler#invoke,有时会调用ExtendedEntityManagerInvocationHandler#invoke,但这并不能告诉我它使用的是哪种EntityManager

    在某些情况下,我什至发现SharedEntityManagerInvocationHandler 包装了ExtendedEntityManagerInvocationHandler

问题是 - 如何确定PersistenceContext 在交易结束时是否关闭?

【问题讨论】:

【参考方案1】:

PersistenceContextType.EXTENDED 没有在任何地方进行评估。 PersistenceAnnotationBeanPostProcessor.java 有一些用法,但是在我的集成测试中断点从未停止过。

当您的任何 bean 中有以下字段声明时,您将遇到断点:

@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;

问题是——如何确定 PersistenceContext 是否在事务结束时关闭?

有趣的问题。如果您仔细研究一下 Spring 代码,您会注意到 SharedEntityManagerInvocationHandler 调用了 EntityManagerFactoryUtils.doGetTransactionalEntityManager()。该方法为返回的EntityManager实例注册一个事务同步:

TransactionSynchronizationManager.registerSynchronization(
                                new TransactionalEntityManagerSynchronization(emHolder, emf, transactionData, false));

该同步是在事务后关闭EntityManager

protected void releaseResource(EntityManagerHolder resourceHolder, EntityManagerFactory resourceKey) 
            closeEntityManager(resourceHolder.getEntityManager());
        

您还会注意到,ExtendedEntityManagerInvocationHandler 并没有这样做。

【讨论】:

以上是关于Spring Boot 中的 PersistenceContext 生命周期的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 中的测试:JUnit

Spring Boot2 系列教程(十三)Spring Boot 中的全局异常处理

Spring Boot2 系列教程Spring Boot 中的静态资源配置

内存数据库spring-boot中的h2

使用 Spring Boot Maven 插件时,jar 文件中缺少 Spring Boot 应用程序中的资源

Spring Boot 实践折腾记:Spring Boot中的容器配置和SSL支持