Spring Boot 中的 PersistenceContext 生命周期
PersistenceContext lifecycle in Spring Boot
我想弄明白 Spring 引导应用程序中的持久性上下文是如何工作的。我使用 Spring Data、Hibernate 和 Hikari。
我无法查明 PersistenceContext
何时创建以及何时关闭。根据几篇文章,例如这篇 https://www.baeldung.com/jpa-hibernate-persistence-context or this one https://dzone.com/articles/how-does-spring-transactional PersistenceContext
生命周期与 EntityManager
生命周期相同。所以我想知道 EntityManager
何时实际创建,更重要的是它何时关闭,最重要的是它是否在事务结束时关闭。根据我的发现,枚举 PersistenceContextType.java
决定了我将拥有什么 PersistenceContext
。 PersistenceContextType.TRANSACTION
应该是默认的,应该导致 SharedEntityManagerInvocationHandler
被用作 EntityManager
的实现并且应该在事务结束时关闭,而 PersistenceContextType.EXTENDED
应该比事务并且应该导致 ExtendedEntityManagerInvocationHandler
正在被使用。所以我试图通过调试来证明它,我发现了以下内容。
PersistenceContextType.EXTENDED
未在任何地方进行评估。 PersistenceAnnotationBeanPostProcessor.java
中有一些用法,但在我的集成测试中断点从未停在那里。
有时会调用SharedEntityManagerInvocationHandler#invoke
,有时会调用ExtendedEntityManagerInvocationHandler#invoke
,这并没有告诉我它使用了哪种EntityManager
。
在某些场合我什至发现 SharedEntityManagerInvocationHandler
包装 ExtendedEntityManagerInvocationHandler
.
问题是 - 如何确定 PersistenceContext
是否在交易结束时关闭?
PersistenceContextType.EXTENDED
is not being evaluated anywhere. There is some usage in PersistenceAnnotationBeanPostProcessor.java
, but the breakpoint never stopped there in my integration tests.
当您的任何 bean 中有以下字段声明时,您将遇到断点:
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;
The question is - how is it determined, if the PersistenceContext is closed at the end of transaction or not?
有趣的问题。如果您深入研究 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 引导应用程序中的持久性上下文是如何工作的。我使用 Spring Data、Hibernate 和 Hikari。
我无法查明 PersistenceContext
何时创建以及何时关闭。根据几篇文章,例如这篇 https://www.baeldung.com/jpa-hibernate-persistence-context or this one https://dzone.com/articles/how-does-spring-transactional PersistenceContext
生命周期与 EntityManager
生命周期相同。所以我想知道 EntityManager
何时实际创建,更重要的是它何时关闭,最重要的是它是否在事务结束时关闭。根据我的发现,枚举 PersistenceContextType.java
决定了我将拥有什么 PersistenceContext
。 PersistenceContextType.TRANSACTION
应该是默认的,应该导致 SharedEntityManagerInvocationHandler
被用作 EntityManager
的实现并且应该在事务结束时关闭,而 PersistenceContextType.EXTENDED
应该比事务并且应该导致 ExtendedEntityManagerInvocationHandler
正在被使用。所以我试图通过调试来证明它,我发现了以下内容。
PersistenceContextType.EXTENDED
未在任何地方进行评估。PersistenceAnnotationBeanPostProcessor.java
中有一些用法,但在我的集成测试中断点从未停在那里。有时会调用
SharedEntityManagerInvocationHandler#invoke
,有时会调用ExtendedEntityManagerInvocationHandler#invoke
,这并没有告诉我它使用了哪种EntityManager
。在某些场合我什至发现
SharedEntityManagerInvocationHandler
包装ExtendedEntityManagerInvocationHandler
.
问题是 - 如何确定 PersistenceContext
是否在交易结束时关闭?
PersistenceContextType.EXTENDED
is not being evaluated anywhere. There is some usage inPersistenceAnnotationBeanPostProcessor.java
, but the breakpoint never stopped there in my integration tests.
当您的任何 bean 中有以下字段声明时,您将遇到断点:
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;
The question is - how is it determined, if the PersistenceContext is closed at the end of transaction or not?
有趣的问题。如果您深入研究 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
不会做这样的事情。