事务范围的持久性上下文和扩展持久性上下文之间有什么区别?
事务范围的持久性上下文和扩展持久性上下文之间有什么区别?
JSR-220 Enterprise JavaBeans 3.0 规范中清楚地解释了这种差异:
5.6 容器管理的持久性上下文
(...)
容器管理的持久性上下文可以定义为具有作用域为单个事务的生存期,也可以定义为具有跨多个事务的扩展生存期,具体取决于创建上下文时指定的生存期。此规范分别引用事务范围的持久性上下文和扩展持久性上下文等持久性上下文。
PersistenceContextType
EntityManager
(...)
5.6.1 容器管理的事务范围的持久性上下文
应用程序可以通过在 JNDI 名称空间中注入或直接查找来获得容器管理的实体管理器,该实体管理器具有绑定到 JTA 事务的事务范围的持久性上下文。实体管理器的持久性上下文类型缺省或定义为 。
PersistenceContextType.TRANSACTION
当在活动 JTA 事务的范围内调用容器管理的实体管理器 [36]时,新的持久性上下文开始,并且没有当前持久性上下文已经与 JTA 事务相关联。创建持久性上下文,然后将其与 JTA 事务相关联。
当关联的 JTA 事务提交或回滚时,持久性上下文结束,并且由 EntityManager 管理的所有实体都变得分离。
如果在事务范围之外调用实体管理器,则在方法调用结束时,从数据库加载的任何实体都将立即分离。
5.6.2 容器管理的扩展持久性上下文
容器管理的扩展持久性上下文只能在有状态会话 Bean 的范围内启动。它从创建声明对实体管理器类型的依赖项的有状态会话 Bean 的点开始存在,并且称为绑定到有状态会话 Bean。对扩展持久性上下文的依赖关系是通过注释或持久性-上下文-ref 部署描述符元素来声明的。
PersistenceContextType.EXTENDED
PersistenceContext
当有状态会话 Bean 的方法完成时,容器会关闭持久性上下文(或者以其他方式销毁有状态会话 Bean 实例)。
@Remove
(...)
有很多细节需要尊重...但为了保持简短,我记得这样的区别:
总之:当调用事务范围的 Bean 上的方法时,容器将自动启动事务,并为您创建新的持久性上下文。当方法结束时,事务结束并且持久性上下文将关闭,您的实体将分离。
效益:此行为是无状态的,不需要您在代码中进行太多维护,并使 EntityManager 线程安全。
总之:只能用于有状态会话 Bean,并且与 Bean 的生命周期相关联。持久性上下文可以跨多个事务生成,这意味着扩展 Bean 中的方法共享相同的持久性上下文。
效益:非常适合与客户实现对话式互动。您的客户端调用了几种Bean方法来告诉您的Bean您需要知道的所有信息,并且在对话结束时,您将所有内容保存到数据库中。
事务传播:假设使用两个方法 A 和 B 为事务范围的 Bean 提供默认的 TransactionAttributes。
如果在方法 A 内部调用方法 B,则可以将 A 的持久性上下文传播到 B。这样,方法 B 甚至可以访问由 A 创建/更改的非持久性实体,因为它们仍由 B 现在有权访问的持久性上下文管理。
事务从扩展到事务范围的传播:您可以通过从扩展 Bean 调用事务范围的 Bean 的方法,将扩展 Bean 的持久性上下文传播到事务范围的 Bean。使用缺省事务属性 (),事务范围的 Bean 将重用扩展 Bean 的现有活动持久性上下文。REQUIRED
事务从事务范围到扩展的事务传播:然而,反过来则不那么直观,因为扩展的持久性上下文总是试图使自身成为活动的持久性上下文。您必须使用 更改扩展 Bean 的默认事务属性。这将在扩展 Bean 方法启动之前挂起任何活动事务(与持久性上下文关联)。@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)