JPA:回滚后刷新分离的实体并重新附加它

时间:2013-10-29 00:37:01

标签: java jpa entity refresh rollback

我有一个接收JPA Entity及其相关EntityManager作为参数的方法。 Entity实例不是在类中创建的,它可能很好地由其他类共享(如GUI等)。

该方法启动一个事务,对实体进行一些更改,最后提交事务。

如果提交失败,则调用EntityTransaction.rollback():根据JPA规范,实体将与经理分离。

如果失败,应用程序需要丢弃挂起的更改,恢复实体e内的原始值并将其重新附加到EntityManager,以便对{的各种分散引用{1}}对象仍然有效。问题出在这里:我理解的是,这不是使用e的API的直接操作:

  • 由于EntityManager已分离,因此无法调用EntityManager.refresh(e)
  • 执行e会为e = EntityManager.merge(e)创建一个新实例:运行时程序中原始e的所有其他引用都不会更新到新实例。这是主要问题。
  • 此外(实际上不太确定),e将使用EntityManager.merge(e)当前保存的值更新新托管实例的值(即,可能导致提交失败的值)。相反,我需要的是重置它们。

示例代码:

e

在这种情况下,最好的方法是什么?

1 个答案:

答案 0 :(得分:0)

可能的解决方案如下:

public class YourClass {
    private EntityManager em = ...; // local entity manager

    public void method(Entity e) { // only entity given here
        Entity localEntity = em.find(Entity.class, e.getId());
        EntityTransaction et = em.getTransaction();
        et.begin();
        ...
        // apply some modifications to the local entity's fields
        applyChanges(localEntity);
        ...
        try {
            et.commit();
            // Changes were successfully commited to the database. Also apply
            // the changes on the original entity, so they are visible in GUI.
            applyChanges(e);
        } catch (Exception ex) {
            et.rollback();
            // original entity e remains unchanged
        }
    }

    private void applyChanges(Entity e) { 
        ... 
    }
}