關(guān)系數(shù)據(jù)庫(kù)映射(行為模式之工作單元)
[問(wèn)題域]
正常情況下,如果使用Data Mapper解決了Domain對(duì)象和數(shù)據(jù)庫(kù)分離的目的,使用時(shí),如果每當(dāng)一個(gè)Domain對(duì)象創(chuàng)建、修改或刪除時(shí),最簡(jiǎn)單的方式就是立即對(duì)數(shù)據(jù)庫(kù)進(jìn)行更新操作,但是這樣會(huì)對(duì)數(shù)據(jù)庫(kù)產(chǎn)生大量的調(diào)用動(dòng)作。如果不這樣做,就必須記錄下Domain對(duì)象的各種修改動(dòng)作,以保證最后提交時(shí),對(duì)數(shù)據(jù)庫(kù)進(jìn)行相應(yīng)的更新,保持Domain對(duì)象和數(shù)據(jù)庫(kù)的一致性。
[解決方案]
找一個(gè)處所保存Domain對(duì)象的各種變化,最后提交時(shí),就知道應(yīng)該要做什么修改,并最終寫(xiě)入數(shù)據(jù)庫(kù)。而這個(gè)處所可以稱(chēng)之為工作單元(Unit of work),使用這種方式被命令為工作單元模式(參考[Martin Fowler企業(yè)架構(gòu)模式])。
工作單元模式(Unit of work)
根據(jù)以上描述可知,工作單元模式包括兩個(gè)主要方面:
1. 記錄操作過(guò)的各種Domain對(duì)象
2. 同步到數(shù)據(jù)庫(kù)中

我們先來(lái)看看如何記錄操作過(guò)的各種Domain對(duì)象。
1.由調(diào)用者注冊(cè)。比如:調(diào)用者創(chuàng)建一個(gè)Domain對(duì)象時(shí),同時(shí)通知工作單元,執(zhí)行了更新操作。
缺點(diǎn):有程序開(kāi)發(fā)者主動(dòng)控制,人是最靠不住的。
有點(diǎn):可以主動(dòng)決定是否注冊(cè),(也就是決定把Domain更改是否寫(xiě)入數(shù)據(jù)庫(kù))
2.由Domain對(duì)象注冊(cè)。比如:Domain對(duì)象中的Create方法中比如加入通知工作單元的代碼,工作單元可以作為參數(shù)傳入,或者固定的地方可以獲取(如ThreadLocal保存)。
缺點(diǎn):也是需要由人在各個(gè)Domain對(duì)象的各種操作中加入固定通知工作單元代碼。
優(yōu)點(diǎn):當(dāng)然具有一致性,同時(shí)就可以采用AOP的思想統(tǒng)一操作(比如Proxy,Minxin等)
3.工作單元控制器。總的思路是,工作單元控制所有的讀操作,讀取對(duì)象的時(shí)候,對(duì)它進(jìn)行注冊(cè)為Clean的,并產(chǎn)生一個(gè)拷貝,提交時(shí),對(duì)比一下哪些字段進(jìn)行了改變,然后再更新。對(duì)于不想拷貝的對(duì)象則需要主動(dòng)進(jìn)行注冊(cè)。(TOPLink使用此方式)
缺點(diǎn):不需要拷貝的對(duì)象需要主動(dòng)注冊(cè),否則一律拷貝一個(gè)。
優(yōu)點(diǎn):對(duì)Domain對(duì)象的改變只進(jìn)行了有選擇的更新。
接下來(lái)討論工作單元同步到數(shù)據(jù)庫(kù)的問(wèn)題:
1.更新順序
如果數(shù)據(jù)庫(kù)允許,只在事務(wù)提交時(shí)檢查引用完整性,而不是每次SQL都檢查,則隨便怎么用都可以。如果數(shù)據(jù)庫(kù)不允許,則在工作單元中則根據(jù)元數(shù)據(jù)(metadata)指定的順序執(zhí)行更新數(shù)據(jù)庫(kù)的操作。
2.批量更新
如果有一些列的更新,刪除或新增操作,則可以在工作單元中,作為一個(gè)單條語(yǔ)句發(fā)送請(qǐng)求。
[結(jié)論]
工作單元最大的好處就是把各種復(fù)雜的操作保存在一個(gè)固定的地方。這種模式可以應(yīng)用于所謂有類(lèi)似需求的地方。
參考資料:
Patterns of Enterprise Application Architecture (author:Martin Fowler)