場(chǎng)景:某一部門有員工20人 業(yè)務(wù):修改該部門名稱 操作:操作由頁面發(fā)起,頁面填寫好了部門信息,Struts得到頁面封裝的數(shù)據(jù) 問題:此時(shí)如果直接對(duì)收集到的對(duì)象進(jìn)行update,那么當(dāng)前對(duì)象是一個(gè)DO對(duì)象(具有OID),在進(jìn)行更新操作時(shí),由于未從頁面上收集到對(duì)應(yīng)的20名員工信息,此時(shí)員工信息集合中沒有數(shù)據(jù)。如果沒有設(shè)置部門對(duì)員工的集合失去關(guān)系維護(hù),那么在進(jìn)行更新操作時(shí),Hibernate會(huì)認(rèn)為該對(duì)象不關(guān)聯(lián)任何數(shù)據(jù),執(zhí)行將關(guān)聯(lián)數(shù)據(jù)表中所有外鍵為當(dāng)前部門OID的數(shù)據(jù)的外鍵設(shè)置為null的操作。一旦更新完畢,就斷開了20名員工與部門間的關(guān)系。 解決方案A: 設(shè)置一方部門失去關(guān)系維護(hù)能力,僅由多方來維護(hù) 操作路徑:在一方的映射配置<set></set> 標(biāo)簽中設(shè)置inverse屬性值為true,Hibernate默認(rèn)為false的 解決方案B: 在業(yè)務(wù)層使用傳遞的OID重新加載部門數(shù)據(jù),操作后將獲取到對(duì)應(yīng)的員工信息集合數(shù)據(jù)。此時(shí)將外部收集的數(shù)據(jù)set到部門對(duì)象中,使用快照進(jìn)行更新 操作:Transaction t = session.beginTransaction(); dm.setName(newDept); t.commit(); A VS B : A方案中,需要?jiǎng)觾蓚€(gè)地方,除了上述配置文件要?jiǎng)油?,還有就是要寫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(); 如果該部門有許多字段信息,得要一個(gè)個(gè)的從頁面中獲取,然后set進(jìn)去 ,或者是從數(shù)據(jù)庫中查詢出來其他的字段信息,然后set進(jìn)去.然后實(shí)際上改變的只是一個(gè)名稱字段信息,執(zhí)行了一個(gè)update的SQL操作,或者執(zhí)行了兩個(gè)SQL操作,一個(gè)是select * ,一個(gè)是update。如果不set其他字段信息,那么就會(huì)將除了名稱和OID之外其他字段信息設(shè)置為NULL,那么新的問題將有可能衍生出來。 再來看B方案: 代碼很簡(jiǎn)潔,只需動(dòng)一個(gè)地方,利用session緩存和快照之間比對(duì)數(shù)據(jù)的關(guān)系來更新數(shù)據(jù),一開始就需要執(zhí)行 兩個(gè)操作,select *和update,很奇怪,并沒有在上述代碼中開到update語句啊,原來session緩存中的通過load進(jìn)來PO對(duì)象的名稱屬性發(fā)生了改變,然后又在commit之前執(zhí)行了flush操作更新了快照,所以Hibernate向數(shù)據(jù)庫發(fā)送了updateSQL語句并且執(zhí)行了該 語句。 注:session緩沖中保存的對(duì)象全是PO,因此PO可以更新數(shù)據(jù)庫對(duì)應(yīng)信息,而TO與DO則不具備這樣的能力 |
|