分享

Hibernate维护一对多关系中常见的两种解决方案的比较

 小清风的doc 2016-10-05
场景:某一部门有员工20人
业务:修改该部门名称
操作:操作由页面发起,页面填写好了部门信息,Struts得到页面封装的数据
问题:此时如果直接对收集到的对象进行update,那么当前对象是一个DO对象(具有OID),在进行更新操作时,由于未从页面上收集到对应的20名员工信息,此时员工信息集合中没有数据。如果没有设置部门对员工的集合失去关系维护,那么在进行更新操作时,Hibernate会认为该对象不关联任何数据,执行将关联数据表中所有外键为当前部门OID的数据的外键设置为null的操作。一旦更新完毕,就断开了20名员工与部门间的关系。

解决方案A: 设置一方部门失去关系维护能力,仅由多方来维护
操作路径:在一方的映射配置<set></set> 标签中设置inverse属性值为true,Hibernate默认为false的

解决方案B:

在业务层使用传递的OID重新加载部门数据,操作后将获取到对应的员工信息集合数据。此时将外部收集的数据set到部门对象中,使用快照进行更新

操作:Transaction t = session.beginTransaction();
       
DepartmentModel dm = (DepartmentModel) session.load(DepartmentModel.class, OID);

       dm.setName(newDept);

        t.commit();

注:commit执行之前会默认执行了session.flush()操作刷新session缓存,根据OID加载部门数据,此时的部门对象在session缓存中,然后将收集到的数据set到部门对象中,利用快照进行更新。

A  VS  B :
A方案中,需要动两个地方,除了上述配置文件要动外,还有就是要写DAO层的代码,

Transaction t = session.beginTransaction();
       
DepartmentModel dm = new DepartmentModel();
         dm.setUuid(OID);
         dm.setXxx1(xxx1);

         dm.setXxx2(xxx2);
         dm.setXxxn(xxxn);   
          dm.setName(newDept);
          session.update(dm);
           t.commit();
如果该部门有许多字段信息,得要一个个的从页面中获取,然后set进去 ,或者是从数据库中查询出来其他的字段信息,然后set进去.然后实际上改变的只是一个名称字段信息,执行了一个update的SQL操作,或者执行了两个SQL操作,一个是select * ,一个是update。如果不set其他字段信息,那么就会将除了名称和OID之外其他字段信息设置为NULL,那么新的问题将有可能衍生出来。

再来看B方案:  代码很简洁,只需动一个地方,利用session缓存和快照之间比对数据的关系来更新数据,一开始就需要执行 两个操作,select *和update,很奇怪,并没有在上述代码中开到update语句啊,原来session缓存中的通过load进来PO对象的名称属性发生了改变,然后又在commit之前执行了flush操作更新了快照,所以Hibernate向数据库发送了updateSQL语句并且执行了该
语句。

注:session缓冲中保存的对象全是PO,因此PO可以更新数据库对应信息,而TO与DO则不具备这样的能力

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多