3

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

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

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

在失败的情况下,应用程序需要丢弃未决的更改,恢复实体内部的原始值e并将其重新附加到EntityManager,以便对e对象的各种分散引用保持有效。问题在这里提出:我的理解是,这不是使用EntityManager's API 的简单操作:

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

示例代码:

public void method(EntityManager em, Entity e) {
    EntityTransaction et = em.getTransaction();
    et.begin();
    ...
    // apply some modifications to the entity's fields
    ...
    try {
        et.commit();
    } catch (Exception e) {
        et.rollback();

        // now that 'e' is detached from the EntityManager, how can I:
        // - refresh 'e', discarding all pending changes
        // - without instantiating a copy (i.e. without using merge())
        // - reattach it
    }
}

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

4

1 回答 1

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) { 
        ... 
    }
}
于 2013-10-30T05:39:13.293 回答