问题
This doesn't work -- I always get the IllegalArgumentException thrown with the advice to "try merging the detached and try the remove again."
@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);
}
}
The output log shows the following:
INFO: delete() entity not managed: com.database.SomeTable[ id=2 ]
INFO: delete() this entity should now be managed: false
In other words the merge() does not return a managed entity. Can anyone spot what I did wrong?
Second question: is there a way to do this in one transaction rather than two?
This is with EclipseLink inside GlassFish 3.1.
回答1:
After commiting your persistence context should be gone. So your println test after the commit will fail, because the "target" object is not managed anymore.
Do all your stuff within one transaction and it should work. You just have to start your transaction after your "try" begins.
回答2:
This snippet of code creates two transactions:
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();
While it is true that the entity is merged into the persistence context, it is true only of the first transaction, and not for both. In the second transaction, the persistence context associated with the transaction will again find a detached object passed as an argument, in the following line:
em.remove(target);
since, the previous utx.commit()
would have detached the reference to target
.
To fix this, you must merge the entity into the persistence context, and delete the entity in the same transaction, before the reference is detached:
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)) );
}
来源:https://stackoverflow.com/questions/7448392/how-do-i-make-my-entity-object-managed-so-i-can-remove-it