您的位置:首页 > Web前端

使用hibernate,在面对复杂业务处理的时候,你是否很顺手,由Exception-found shared references to a collection说开去

2008-01-31 16:15 381 查看
先大概说一下项目的需求:因为一个生产评估(Estimation)可能需要从一个旧的版本的数据,因为他们都很想像,比如说这个工厂上次帮KFC生产了一批cake box,这是是麦当劳的订单,也是需要生产一批蛋糕盒子,size和工艺和机器等都是差不多的,所以不比从新开始,而需要dulicate一下,然后进去稍微做些修改。所以我们需要从在后台做一个batch bob,从旧的数据复制些数据,大概是从9张表,先查询,然后再insert。本来假如没有使用hibernate的时候,逻辑很简单,查询,循环插入。但是后来却发现一直由

“found shared references to a collection”!!!

困扰了大概一天时间,两个人。后来发现是session和transaction这两东东从中作梗。因为我们的数据是关联的,设置了lazy=false。在service层先得到这个数据,方法是大概是这样的

public void saveEstaimtionFromOldVersion(Integer oldVersionEstimationId){

List list =estimationDao.getEstiamtionById(oldVersionEstimationId);

for(Iterator it =list.iterator;it.hasNext();){

//processOneRecord

//save New data to 9 tables......

}

}

这个方法是写在service层,我们的借助spring的事务控制也是在这一层。

通过debug的时候,一切正常,但是当线程离开这个方法的时候,报了上面的这个错误。后来我们就怀疑是session没有释放从数据库查询出来的数据--官方成这个叫非托管的Bean,因为一直是在service层,session永远都不会flush()注意这个flush()动作都是由spring来控制的;session不做flush()动作,所以里面的哪些对象的reference一直存在,由于新的reference是在new出来的。后来我做了一个改动,就是把数据循环出来的时候,就把内存的哪些reference=null;这样一切正常.但是这样代码里充斥着很多这样的跟业务无关的代码,这些代码就是使用hibernate的代价。

后来把程序改动了一下。

public void saveEstaimtionFromOldVersion(List oldEstimation){//这里不是Integer,而是一个List

for(Iterator it =oldEstimation.iterator;it.hasNext();){

//processOneRecord

//save New data to 9 tables......

}

}

把这个查询的数据的动作放在这个batchjob之前完成。。。

一切正常。。。

还有一个解决方法:假如不使用hibernate的级联,关联这些特性----remove all many2one,one2many,这样通过hql或者sql查询出来的数据也会正常。我猜想,通过sql来查询的话,session会特殊处理,不会留有reference在session里。

欢迎交流。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐