日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
實(shí)現(xiàn)資源庫(kù)還沒(méi)找到稱手的家伙

?[[357638]]?

成都創(chuàng)新互聯(lián)公司長(zhǎng)期為千余家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為黃梅企業(yè)提供專業(yè)的成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè),黃梅網(wǎng)站改版等技術(shù)服務(wù)。擁有10余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。

本文轉(zhuǎn)載自微信公眾號(hào)「codeasy」,作者閻華。轉(zhuǎn)載本文請(qǐng)聯(lián)系codeasy公眾號(hào)。

用UOW模式實(shí)現(xiàn)Repository

看了《無(wú)法實(shí)施富領(lǐng)域模型的罪魁禍?zhǔn)渍业搅恕愤@一篇文章后,很多人都會(huì)問(wèn)這種Repository是這么實(shí)現(xiàn)的。這種Repository的實(shí)現(xiàn)背后用了一個(gè)叫做 “Unit of Work (UOW)”的模式:

Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.Unit of Work --Martin Fowler

UOW模式是在業(yè)務(wù)用例的操作中跟蹤對(duì)象的所有更改(增加、刪除和更新),并將所有更改的對(duì)象保存在一個(gè)列表中。在業(yè)務(wù)用例的終點(diǎn),通過(guò)事務(wù),一次性提交所有更改,以確保數(shù)據(jù)的完整性和有效性??偠灾琔OW協(xié)調(diào)這些對(duì)象的持久化及并發(fā)問(wèn)題。

??

很多實(shí)現(xiàn)了UOW模式的框架都采用了保存快照的方式來(lái)跟蹤對(duì)象狀態(tài)的變化,如上圖所示,通過(guò)對(duì)比開(kāi)始時(shí)對(duì)象的狀態(tài)和編輯后的對(duì)象的狀態(tài),從而決定如何更新數(shù)據(jù)庫(kù)。這樣做的好處是可以增量按需更新。

重點(diǎn)是最后一次性保存變更,跟蹤對(duì)象狀態(tài)的變更不是必須的,我們看看IDDD_Sample是怎么實(shí)現(xiàn)的。

IDDD_Sample使用了LevelDB來(lái)存儲(chǔ)數(shù)據(jù),以 agilepm.port.adapter.persistence.LevelDBSprintRepository 為例:

void save(Sprint aSprint, LevelDBUnitOfWork aUoW) {
LevelDBKey primaryKey = new LevelDBKey(PRIMARY, aSprint.tenantId().id(), aSprint.sprintId().id());
aUoW.write(primaryKey, aSprint);
}

其中 LevelDBUnitOfWork 的write方法是這么實(shí)現(xiàn)的:

public void write(LevelDBKey aKey, Object aValue) {
String serializedValue = this.serializer.serialize(aValue);
this.batch.put(aKey.keyAsBytes(), serializedValue.getBytes());
}

它把整個(gè)聚合序列化后存儲(chǔ)了。由于沒(méi)有跟蹤對(duì)象變更,所以也無(wú)法實(shí)現(xiàn)增量的更新,只能粗暴地用最新的聚合序列化后完全覆蓋之前的聚合存儲(chǔ)了。 但這種方式對(duì)我們大部分場(chǎng)景參考性不大,一個(gè)原因是我們最常用的還是關(guān)系型數(shù)據(jù)庫(kù), 另一個(gè)原因是這種非增量的更新開(kāi)銷還是比較大的。

合適的就是最好的,我有個(gè)朋友曾用MongoDB作存儲(chǔ),使用了這樣的模式,效果很好,他所做的那個(gè)應(yīng)用數(shù)據(jù)量不大,并發(fā)不高,用這種方式大大節(jié)約了開(kāi)發(fā)和維護(hù)的成本。

那我們看看當(dāng)使用關(guān)系型數(shù)據(jù)庫(kù)的時(shí)候有什么框架可以選擇。

使用JPA實(shí)現(xiàn)Repository

JPA (Java Persistence API) 是一個(gè)Java 持久化規(guī)范,最流行的一個(gè)實(shí)現(xiàn)是Hibernate,它可以大大簡(jiǎn)化對(duì)數(shù)據(jù)庫(kù)的操作,然而,JPA在國(guó)內(nèi)不受待見(jiàn):

然而要實(shí)現(xiàn)UOW模式的Repository,使用JPA依然是最佳選擇,你幾乎不用自己做任何的工作,只要把聚合中的對(duì)象和表映射好就可以了。

JPA/Hibernate還提供了易用的樂(lè)觀鎖功能,在聚合根上維護(hù)一個(gè)樂(lè)觀鎖非常簡(jiǎn)單

JPA/Hibernate在國(guó)內(nèi)不受待見(jiàn)的一個(gè)重要原因,不是它不好用,而是太好用了——隱藏了很多實(shí)現(xiàn)細(xì)節(jié)有時(shí)候顯得不太靈活,提供了太多的高級(jí)功能用不好容易踩坑。

所以,使用JPA,請(qǐng)遵循以下幾點(diǎn)建議:

  • 只用它的功能的一個(gè)子集,比如要禁用Many-to-Many映射、禁用延遲加載的功能等;
  • 還記得之前關(guān)于CQRS這篇文章吧,很多查詢場(chǎng)景不需要聚合內(nèi)的全部數(shù)據(jù),所以,有些Query的實(shí)現(xiàn),你完全可以不使用JPA,而是用原始的SQL去查,比如用JDBC或MyBatis;理解了CQRS,這些技術(shù)是可以很好地結(jié)合在一起使用的;
  • 確定你的聚合中的數(shù)據(jù)不需要分庫(kù)分表。即使你使用了Proxy模式的分庫(kù)分表中間件,使用JPA還是有問(wèn)題的,這個(gè)以后專門(mén)寫(xiě)一篇文章說(shuō)說(shuō)為什么有問(wèn)題,以及如何解決這個(gè)問(wèn)題;

嫌棄JPA不夠精簡(jiǎn)的人很多,以至于Spring的官方推出了 Spring-Data-JDBC,一個(gè)專門(mén)為DDD的聚合存儲(chǔ)設(shè)計(jì)的ORM框架,它比JPA輕量很多,簡(jiǎn)單很多,然而,為了輕量簡(jiǎn)單,它也沒(méi)有對(duì)對(duì)象狀態(tài)修改進(jìn)行跟蹤,所以在保存聚合的時(shí)候無(wú)法像JPA一樣按需更新數(shù)據(jù)庫(kù),而是如IDDD_Sample一樣,粗暴地覆蓋更新,甚至?xí)葎h除聚合下所有子實(shí)體后再重新插入(無(wú)論子實(shí)體數(shù)據(jù)有沒(méi)有變更),這可能會(huì)帶來(lái)不可控的性能問(wèn)題。

如果我們又想用關(guān)系數(shù)據(jù)庫(kù),又不能使用JPA,那還有別的辦法嗎?

自己寫(xiě)代碼實(shí)現(xiàn)資源庫(kù)

前段時(shí)間我嘗試過(guò)一種方法:自己手寫(xiě)Repository的實(shí)現(xiàn),在聚合保存前,先從庫(kù)里load出來(lái)一個(gè)聚合,把這兩個(gè)聚合里的對(duì)象進(jìn)行比較(diff),找出差異,生成操作數(shù)據(jù)庫(kù)的SQL語(yǔ)句,去增量更新數(shù)據(jù)庫(kù)。

這樣做的問(wèn)題是需要寫(xiě)很多的Repository代碼,而且很容易出錯(cuò)也不容易維護(hù),我試圖做一些抽象來(lái)簡(jiǎn)化代碼,最后發(fā)現(xiàn)抽象越多越像JPA了。

這樣做還有一個(gè)問(wèn)題是需要在保存前額外加載一次,如果想避免這個(gè)問(wèn)題,可以看看《DDD之聚合持久化應(yīng)該怎么做?| https://zhuanlan.zhihu.com/p/334344752》,但這種方法還是沒(méi)有避免需要寫(xiě)很多代碼的問(wèn)題。

自己編碼實(shí)現(xiàn)的好處是可控,比如容易處理分庫(kù)分表的問(wèn)題。但實(shí)現(xiàn)起來(lái)太復(fù)雜,編寫(xiě)和維護(hù)成本高,也容易出問(wèn)題,這大大打擊了使用富領(lǐng)域模型的熱情。

總之,實(shí)現(xiàn)Repository,還沒(méi)有一件稱手的家伙。

再次審視端口適配器模型

前面我們提到過(guò)DDD提倡的六邊形模型,即端口適配器模型,Repository就是一個(gè)例子。比如接口 agilepm.domain.model.product.sprint.SprintRepository 這是一個(gè)接口,即所謂的端口,它和領(lǐng)域?qū)ο笤谕粋€(gè)包里;而 agilepm.port.adapter.persistence.LevelDBSprintRepository這個(gè)實(shí)現(xiàn)是在另外的叫 adapter 的包下,這背后體現(xiàn)的是依賴倒置原則,這樣可以讓領(lǐng)域?qū)雍蛻?yīng)用層不依賴于具體的技術(shù)實(shí)現(xiàn)。

Repository的實(shí)現(xiàn)只是一種adapter,下一篇我們講一講如何訪問(wèn)另一個(gè)上下文中的服務(wù),那本質(zhì)上也是一種port/adapter,但有更多的不一樣的細(xì)節(jié)需要注意。


網(wǎng)頁(yè)標(biāo)題:實(shí)現(xiàn)資源庫(kù)還沒(méi)找到稱手的家伙
本文來(lái)源:http://www.5511xx.com/article/djhshpe.html