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

先大概说一下项目的需求:因为一个生产评估(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里。

欢迎交流。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值