【问题标题】:How do I make my entity object managed so I can remove it?如何管理我的实体对象以便我可以删除它?
【发布时间】:2011-09-16 17:35:14
【问题描述】:

这不起作用——我总是抛出 IllegalArgumentException 并建议“尝试合并分离的并再次尝试删除”。

@PersistenceContext private EntityManager   em;
@Resource           private UserTransaction utx;
public void delete(EN entity) {
    if (entity == null) return;   // null-safe
    EN target = entity;
    try {
        if (!em.contains(entity)) {
            System.out.println("delete() entity not managed: " + entity);
            utx.begin();
            target = em.merge(entity);
            utx.commit();
            System.out.print("delete() this entity should now be managed: " + em.contains(target));
        }
        utx.begin();
        em.remove(target);
        utx.commit();
    } catch (RollbackException ex) {
        Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
    } catch (HeuristicMixedException ex) {
        Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
    } catch (HeuristicRollbackException ex) {
        Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
    } catch (SecurityException ex) {
        Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalStateException ex) {
        Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
    } catch (NotSupportedException ex) {
        Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
    } catch (SystemException ex) {
        Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
    }
}

输出日志显示如下:

INFO: delete() entity not managed: com.database.SomeTable[ id=2 ]  
INFO: delete() this entity should now be managed: false

换句话说,merge() 不返回托管实体。谁能发现我做错了什么?

第二个问题:有没有办法在一次交易而不是两次交易中做到这一点?

这是 GlassFish 3.1 中的 EclipseLink。

【问题讨论】:

  • 您是否尝试过在事务中而不是在外部进行合并?

标签: jpa jpa-2.0


【解决方案1】:

这段代码创建了两个事务:

if (!em.contains(entity)) {
    System.out.println("delete() entity not managed: " + entity);
    utx.begin();
    target = em.merge(entity);
    utx.commit();
    System.out.print("delete() this entity should now be managed: " + em.contains(target));
}
utx.begin();
em.remove(target);
utx.commit();

虽然实体被合并到持久化上下文中是真的,但它只适用于第一个事务,而不适用于两者。在第二个事务中,与事务关联的持久化上下文将再次找到一个作为参数传递的分离对象,如下行:

em.remove(target);

因为之前的utx.commit() 会分离对target 的引用。

要解决此问题,您必须将实体合并到持久化上下文中,并在同一事务中删除实体,然后再分离引用:

if (!em.contains(entity)) {
    System.out.println("delete() entity not managed: " + entity);
    utx.begin();
    target = em.merge(entity);
    em.remove(target);
    utx.commit();
    System.out.print("delete() this entity should now be deleted: " + (!em.contains(target)) );
}

【讨论】:

    【解决方案2】:

    提交持久性上下文后,应该消失了。所以提交后你的 println 测试将失败,因为“目标”对象不再被管理。

    在一笔交易中完成所有工作,它应该可以工作。您只需在“尝试”开始后开始交易。

    【讨论】:

    • 爸爸口香糖很好用。我以为我以前尝试过,但没有。感谢您的帮助。
    • 如果使用“扩展”持久性上下文,原始合并将使对象保持托管状态。
    猜你喜欢
    • 2021-05-31
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 2018-11-13
    • 2015-09-17
    • 2015-03-11
    • 2012-03-09
    • 2022-12-03
    相关资源
    最近更新 更多