EJB/JPA事务边界

Bhu*_*van 7 java hibernate jpa transactions ejb-3.0

我正在阅读 EJB Transaction boundary和Transaction boundary

让我们专注于RequiresNew Attribute.

这是链接的修改图

在此输入图像描述

所以,让我们说method-B注释RequiredNew attribute.

所以根据理论,当method-A调用method-B新事务时将启动并且已经启动的事务将被暂停,并且当method-B返回时将提交新事务.


现在考虑在S1我们创建一个jpa实体的部分entitymanager.persist(),现在我们将这个实体传递给实体method-Bname字段.

现在当我们从db中返回method-B如何commit进行事务时,实体未被启动的挂起事务提交method-A


PS:Db以读取提交的隔离级别运行.

Nic*_*kJI 6

在这种情况下发生的事情受以下因素控制:

  1. JPA持久化上下文及其与JTA事务的关系.
  2. Java的" 传递引用 " 的行为,在本地接口上传递参数.(参见本答复末尾的引用说明)

使用@PersistenceContext注释创建实体管理器将导致创建Transaction-Scoped实体管理器以及persistence.xml文件定义的关联持久性上下文.上下文将跟踪您指定的类型的实体persistence.xml.在持久化,find(em.find())或合并后,实体将在该上下文中进行管理.上下文将与当前运行的JTA事务关联.当此事务结束时,持久化上下文中存在的更改可以刷新并提交 - 或者如果事务本身回滚则回滚.

在示例场景中,假设使用Bean2的本地接口.当Bean2-MethodB被调用,因为该方法与注解一个新的事务被启动@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW).调用方法的事务被暂停.没有持久性上下文与新创建的事务关联.但是,传入的实体将引用由其处理的实体的相同实例Bean1-MethodA,并且此实例是Bean1的实体管理器的持久性上下文中的管理实体.因此,即使与此持久性上下文关联的事务被挂起,对从另一个事务中修改该实体也没有限制.

所以,事件的名义序列是;

  1. Bean1-MethodA 被叫,TransactionA启动.
  2. Transaction-Scoped Entity Manager创建了与TransactionA关联的持久性上下文.
  3. Bean1-MethodA调用Bean2MethodB并传入'entity'作为参数.
  4. 新交易 - TransactionB启动,TransactionA暂停.
  5. Bean2-MethodB修改字段 entity.name.
  6. Bean2-MethodB完成并且TransactionB提交.
  7. TransactionB JTA持久资源提交 - 实体处于与TransactionA关联的持久性上下文中,因此未提交.
  8. Bean1-MethodA和其关联的TransactionA一样恢复.
  9. 进行的实体更改对持久性上下文Bean2-MethodB是可见的Bean1-MethodA
  10. Bean1-MethodA 完成后,TransactionA提交和持久化上下文更改被刷新/提交到DB
  11. - > DB包含字段更改 Bean2-MethodB

当Bean2-MehodB的交易回滚时会发生什么?

值得注意的是,如果在实体字段更改Bean2-MethodBBean2-MethodB’s事务回滚中,则不会还原对类字段的更改.任何JTA资源都将回滚,但实体字段更改仍会反映在数据库中如果Bean1-MehodA成功完成,则会导致潜在的不一致.也许真实世界的问题可能会迫使这样的解决方案,但可能更好地修改事务中可以回滚这些更改的实体.

上述场景在eclipse-mars/WildFly8.2/HibernateJPA/Derby上进行了测试

使用远程EJB调用

这里,实体参数被序列化,从而产生实体的副本Bean2-MethodB.此副本与使用的副本不同Bean1-MethodA,它是一个分离的实体,不与之共享Bean1-MethodA.(这有时称为按值传递,请参阅本答案末尾的注释).为了使更改能够反映在Bean1-MethodA’s持久性上下文中,需要Bean1-MethodA使用实体管理器将实体返回到持久化上下文,然后将其合并到持久性上下文中.无论远程ejb调用是否在事务中进行,都需要进行此合并.

关于"按引用传递"和"按值传递"的注释.

根据定义,java中的所有参数都按值传递.有关堆栈溢出的良好扩展讨论,请参阅Java"pass-by-reference"或"pass-by-value"?.这里重要的是,对于本地接口,Java将引用的副本 - 指针 - 传递给共享实例 - 这是人们通常理解的"传递引用".远程接口在远程端创建实体实例的副本,因此调用方法无法看到对此副本的任何更改.这有时被称为按值传递.