Hibernate的非延迟加载的删除写法

      由于项目比较小,因而没用延迟加载。所有的延迟都是false,这样容易造成以下问题:

  session = this.getSession();
tx = session.beginTransaction();

session.delete(handset);
tx.commit();


以上的代码没有错误不过在添加级联删除后,代码如下:

  session = this.getSession();
tx = session.beginTransaction();
//删除级联关系!!
List<CheckLock> checkLocks = session.createQuery("from CheckLock cl where cl.handset.handsetId = "+
handset.getH andsetId()).list();
for(int i =0 ; i<checkLocks.size() ; i++){
checkLocks.get(i).setHandset(null);
}
session.delete(handset);
tx.commit();


结果会报:a different object with the same identifier value was already associated with the session

问题原因:这是由于handset传来时是session.close的,就是说它是非持久状态的。而对于方法内部的session,由于它进行了级联查询,又由于延迟得关闭,所以当session查出CheckLock的同时也将其级联的handset对象查出并纳入session管理之中,这时就存在一条数据库记录2个handset对象的情况。一个是被传进来,非持久的不被session管理的handset,一个是通过级联查询的被session 管理的handset,。所以由于你删除的是非持久化handset,它要先纳入session的管理,就是持久化但是显然此时的session内已经有个Handset对象因而会抛出上述异常

问题的解决:
没什么好的解决方法,最好是传来ID之后重新查出handset删除就会没问题(以前觉得这种方式不好,会使得 dao重新查询数据库。其实是我多心了,由于级联查询造就将handset存于内存中。因而Hibernate只须调用缓存即可获得结果。)

PS:查了一下hql的删除方法:
int i = session.createQuery("delete Handset hs where hs.handsetId = " + handsetId).executeUpdate();
返回的是更新(删除)的记录数。不过
executeUpdate 方法是直接单独执行的,它不会等待事物的提交。

你可能感兴趣的:(DAO,Hibernate,项目管理)