EJB / JPA事务边界

时间:2015-06-04 06:15:33

标签: java hibernate jpa transactions ejb-3.0

我正在读书 EJB Transaction boundary and Transaction boundary

让我们专注于RequiresNew Attribute

以下是链接

的修改图

enter image description here

因此,请说method-B注明RequiredNew attribute

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

现在考虑在S1部分,我们使用entitymanager.persist()创建一个jpa实体,现在我们将此实体传递给method-B,它设置实体的name字段。 / p>

现在当我们从method-B返回时,如果commit事务如同在db中一样,那么实体未被method-A启动的暂停事务提交?

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

1 个答案:

答案 0 :(得分:5)

此方案中的情况受以下因素控制:

  1. JPA持久性上下文及其与JTA事务的关系。
  2. Java的“ pass-by-reference 参数传递在本地接口上的行为。 (参见本答复末尾的引用说明)
  3. 使用@PersistenceContext注释创建实体管理器会导致创建一个Transaction-Scoped实体管理器以及persistence.xml文件定义的关联持久性上下文。上下文将跟踪persistence.xml中指定类型的实体。在持久化,找到(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. 新交易 - 交易B启动,交易A暂停。
    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. - &GT;数据库包含Bean2-MethodB
    12. 中的字段更改

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