事务范围的持久性上下文和扩展持久性上下文有什么区别?

Transaction-scoped Persistence上下文和Extended Persistence上下文有什么区别?

JSR-220 Enterprise JavaBeans 3.0规范清楚地说明了这个区别:

5.6容器pipe理的持久性上下文

(……)

容器pipe理的持久性上下文可以定义为具有作用域为单个事务的生命周期或跨越多个事务的扩展生命周期,具体取决于创buildEntityManager时指定的PersistenceContextType 。 本规范将这种持久化上下文分别称为事务范围持久化上下文扩展持久化上下文

(……)

5.6.1容器pipe理的事务范围的持久性上下文

应用程序可以通过在JNDI名称空间中进行注入或直接查找来获取绑定到JTA事务的事务范围持久性上下文的容器pipe理实体pipe理器。 实体pipe理器的持久化上下文types是默认的,或者定义为PersistenceContextType.TRANSACTION

当一个活动JTA事务的范围内调用容器pipe理实体pipe理器[36]时,新的持久化上下文开始,并且当前没有持久化上下文已经与JTA事务相关联。 持久化上下文被创build,然后与JTA事务相关联。

当关联的JTA事务提交或回滚时,持久化上下文结束,由EntityManagerpipe理的所有实体都被分离。

如果实体pipe理器在事务范围之外被调用,那么从数据库加载的任何实体将在方法调用结束时立即分离。

5.6.2容器pipe理的扩展持久化上下文

容器pipe理的扩展持久化上下文只能在有状态会话bean的范围内启动。 它存在于声明对PersistenceContextType.EXTENDEDtypes的实体pipe理器的依赖关系的有状态会话bean被创build的地方,并被称为绑定到有状态会话bean。 通过PersistenceContext注释或persistence-context-ref部署描述符元素来声明对扩展持久化上下文的依赖性。

当有状态会话bean的@Remove方法完成时(或者有状态会话bean实例被销毁),持久化上下文被容器closures。

(……)

事务作用域持久化上下文

顾名思义,事务范围的持久化上下文与事务的生命周期相关联。 它在事务中由容器创build,并在事务完成时closures。

事务范围的实体pipe理器负责在需要时自动创build事务范围的持久化上下文。 我们只在需要时才说,因为transactionscoped持久性上下文创build是懒惰的。

实体pipe理器只有在实体pipe理器上调用方法并且没有可用的持久化上下文时才会创build持久化上下文。

扩展的持久性上下文

扩展持久化上下文的生命周期与绑定到的有状态会话bean绑定在一起。

与为每个事务创build新持久化上下文的事务范围实体pipe理器不同,有状态会话bean的扩展实体pipe理器始终使用相同的持久性上下文。

有状态会话bean与一个扩展持久化上下文相关联,该持久化上下文在创buildbean实例时创build,并在删除bean实例时closures。 这对扩展持久化上下文的关联和传播特性都有影响。

有很多细节要尊重…但要保持简短我记得这样的区别:

事务范围的持久性上下文

简而言之:在调用事务范围的bean的方法时,事务将自动由容器启动,并为您创build新的持久化上下文。 当方法结束时,事务结束,持久化上下文将被closures,你的实体将被分离。

好处:这种行为是无状态的,在代码中不需要太多的维护,并使EntityManager线程安全。

扩展的持久性上下文

简而言之:只能用于有状态会话bean,并且与bean的生命周期相关联。 持久化上下文可以跨越多个事务产生,这意味着你的扩展bean中的方法共享相同的持久化上下文。

好处:完美实现与客户的对话风格交互。 你的客户调用多个bean方法来告诉你的bean所有你需要知道的信息,并且在对话结束时你将所有东西都保存到你的数据库中。

重要的事情要知道

事务传播:使用两种方法A和B来为事务范围的bean假设默认的TransactionAttributes 。

如果在方法A中调用方法B,则可以将A的持久化上下文传播到B.这样,方法B可以访问由A创build/更改的非持久化实体,因为它们仍由B上的持久化上下文pipe理现在已经访问。

扩展到事务范围的事务传播:您可以通过从您的扩展bean中调用事务范围的bean的方法,将扩展bean的持久化上下文传播到事务范围的bean。 使用默认事务属性( REQUIRED ),事务范围的bean将重用已经存在的,扩展bean的活动持久化上下文。

事务范围扩展到事务扩展的事务传播:然而,另一种方式并不直观,因为扩展的持久化上下文总是试图使自己成为活动的持久化上下文。 您必须使用@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)更改扩展bean的默认事务属性。 这将在扩展bean方法启动之前暂停任何活动事务(与持久性上下文相关联)。