JPA+Hibernate出错java.lang.IllegalArgumentException: Removing a detached instance
JPA+Hibernate Junit4做批量删除时出错:
批量删除方法如下:
(private?EntityManager em)
?
/** * 批量删除实体 * 可实体批量删除操作,在一个transaction中完成 * 任何Exception发生,全部更新操作回滚 * @param entityClass 实体类 * @param entityids 实体id数组 */public void batchDelete(List<T> entities){for(int i = 0; i<entities.size(); i++){em.remove(entities.get(i));}}
?junit测试出现以下错误:
java.lang.IllegalArgumentException: Removing a detached instance com.agiliti.bean.person.Person#47
..................
原因:
em调用remove时,Hibernate仍然还处于“detach”状态,在Hibernate文档中关于detach叙述:
Detached - a detached instance is an object that has been persistent, but its Session has been closed. The reference to the object is still valid, of course, and the detached instance might even be modified in this state. A detached instance can be reattached to a new Session at a later point in time, making it (and all the modifications) persistent again.?
此时,Session已经关闭,但引用仍然存在(换句话说,heap里的对象没有了)。所以此时必须再次产生一个Session(在heap里产生对象):
解决方法之一——在删除之前把这个Detached instance绑定到当前的Sesssion,在用当前Sesssion删除此instance。getEntityManager()提供merge方法实现:
?
public void batchDelete(List<T> entities){for(int i = 0; i<entities.size(); i++){em.remove(em.merge(entities.get(i)));}}?
?
请注意:如果写成:
仍然错误写法
public void batchDelete(List<T> entities){for(int i = 0; i<entities.size(); i++){em.merge(entities.get(i)); em.remove(entities.get(i));}}
?原因是执行完merge还是detached, merge后返回的新对象才是允许删除的。
?
?
?
?