如何管理我的实体对象,以便将其删除?

时间:2011-09-16 17:35:15

标签: jpa jpa-2.0

这不起作用 - 我总是抛出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。

2 个答案:

答案 0 :(得分:5)

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

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)) );
}

答案 1 :(得分:3)

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

在一次交易中完成所有内容,它应该有效。您只需在“尝试”开始后开始交易。