场景:某一部门有员工20人 业务:修改该部门名称 操作:操作由页面发起,页面填写好了部门信息,Struts得到页面封装的数据 问题:此时如果直接对收集到的对象进行update,那么当前对象是一个DO对象(具有OID),在进行更新操作时,由于未从页面上收集到对应的20名员工信息,此时员工信息集合中没有数据。如果没有设置部门对员工的集合失去关系维护,那么在进行更新操作时,Hibernate会认为该对象不关联任何数据,执行将关联数据表中所有外键为当前部门OID的数据的外键设置为null的操作。一旦更新完毕,就断开了20名员工与部门间的关系。 解决方案A: 设置一方部门失去关系维护能力,仅由多方来维护 操作路径:在一方的映射配置<set></set> 标签中设置inverse属性值为true,Hibernate默认为false的 解决方案B: 在业务层使用传递的OID重新加载部门数据,操作后将获取到对应的员工信息集合数据。此时将外部收集的数据set到部门对象中,使用快照进行更新 操作:Transaction t = session.beginTransaction(); dm.setName(newDept); t.commit(); 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则不具备这样的能力 |
|