日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

DDD - 聚合与聚合根_如何理解 Respository与DAO

發布時間:2025/3/21 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DDD - 聚合与聚合根_如何理解 Respository与DAO 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • Pre
  • Question
  • 如何理解 聚合和聚合根
  • 利用聚合解決業務上的原子性操作
  • 如何確定聚合和聚合根
  • Respository VS DAO


Pre

通常情況,我們都會面臨這樣的一個問題: 架構圖說的是一回事,代碼說的卻是另一回事 。 當然了這里面的影響因素很多,有一個原因就是某些約束沒有在設計中體現出來,也就是說設計的表現力不夠 , 而這些約束需要閱讀代碼才能夠知道,這就增加了理解和使用這個組件的難度。

這個問題在基于數據建模的設計方法上比較明顯, 舉個例子:

DDD - 如何理解Entity與VO提到的購物場景 ,我們以數據驅動的方式來設計訂單和產品表,

CREATE TABLE `order` (`rec_id` BIGINT(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',`seller_id` BIGINT(11) NOT NULL COMMENT '賣家',`buyer_id` BIGINT(11) NOT NULL COMMENT '買家',`price` BIGINT(11) NOT NULL COMMENT '訂單總價格,按分計算',...PRIMARY KEY (`rec_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;CREATE TABLE `order_detail` (`rec_id` BIGINT(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',`order_id` BIGINT(11) NOT NULL COMMENT '訂單主鍵',`product_name` VARCHAR(50) COMMENT '產品名稱',`product_desc` VARCHAR(200) COMMENT '產品描述',`product_price` BIGINT(11) NOT NULL COMMENT '產品價格,按分計算',...PRIMARY KEY (`rec_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

從表關系上,只能知道order與order_detail是一對多的關系。


CREATE TABLE `product` (`rec_id` BIGINT(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',`name` VARCHAR(50) COMMENT '產品名稱',`desc` VARCHAR(200) COMMENT '產品描述',...PRIMARY KEY (`rec_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;CREATE TABLE `product_comment` (`rec_id` BIGINT(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',`product_id` BIGINT(11) NOT NULL COMMENT '產品',`cont` VARCHAR(2000) COMMENT '評價內容',...PRIMARY KEY (`rec_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

從表關系上,也只能知道product與product_comment之間是一對多的關系


Question

Q: order與order_detail之間的關系與product與product_comment之間的關系是一樣的嗎 ?

這mmp, 單單從數據模型上完全區分不出來啊 ,那只能看下業務代碼

@Service @Transactional public class OrderService {public void createOrder(Order order,List<OrderDetail> orderDetailList) throws Exception {// 保存訂單// 保存訂單詳情}} }@Service @Transactional public class ProductService {public void createProduct(Product prod) throws Exception {// 保存產品}} }
  • 訂單和訂單明細是一起保存的,也就是說兩者可以作為一個整體來看待 (這個整體就是我們說的聚合)
  • 產品和產品評論之間并不能被看做一個整體,所以沒有在一起進行操作

這層邏輯,光看上面的設計是看不出來的,只有看到代碼了,才能理清這一層關系 , 無形中就增加了理解和使用難度。

「聚合」就是緩解這種問題的一種手段!


如何理解 聚合和聚合根

public class Artisan {public void say() {System.out.println("1");System.out.println("2");} }

對于上面的代碼,如何保障在多線程情況下1和2能按順序打印出來?最簡單的方法就是使用synchronized關鍵字進行加鎖操作

public class Artisan {public synchronized void say() {System.out.println("1");System.out.println("2");} }

synchronized保證了代碼的原子性執行. 就像 事務保證了原子性操作一樣。

但是,這和「聚合」有什么關系呢?

如果說,synchronized是多線程層面的鎖;事務是數據庫層面的鎖,那么「聚合」就是業務層面的鎖!

在業務邏輯上,有些對象需要保持操作上的原子性,否則就沒有任何意義。這些對象就組成了「聚合」!


利用聚合解決業務上的原子性操作

對于上面的訂單與訂單詳情,從業務上來看,訂單與訂單明細需要保持業務上的原子性操作

  • 訂單必須要包含訂單明細
  • 訂單明細必須要屬于某個訂單
  • 訂單和訂單明細被視為一個整體,少了任何一個都沒有意義

所以其對象模型可以表示為:

  • 訂單和訂單明細組成一個「聚合」
  • 訂單是操作的主體,所以訂單是這個「聚合」的「聚合根」
  • 所有對這個「聚合」的操作,只能通過「聚合根」進行


相應的,產品和產品評價就不構成「聚合」。雖然在表設計時,訂單和訂單明細的結構關系與產品與產品評價的結構關系是一樣的!因為:

  • 雖然產品評價需要屬于某個產品
  • 但是產品不一定就有產品評價
  • 產品評價可以獨立操作

所以產品與產品評論的模型則可以表示為:

  • 產品和產品評論是兩個「聚合」
  • 產品評論通過productId與「產品聚合」進行關聯

如何確定聚合和聚合根

對象在業務邏輯上是否需要保證原子性操作是確定聚合和聚合根的其中一個約束。

還有一個約束就是「邊界」,即聚合多大才合適?過大的「聚合」會帶來各種問題。

還是以鎖舉例,看下面的代碼

public class Artisan{public synchronized void say() {System.out.println("0");System.out.println("1");System.out.println("2");System.out.println("4");} }

只希望12能按順序打印出來,而0和4沒有這個要求!上面的代碼能滿足要求,但是影響了性能。優化方式是使用同步塊,縮小同步范圍:

public class Artisan{public void say() {System.out.println("0");synchronized(Locker.class){System.out.println("1");System.out.println("2");}System.out.println("4");} }

「邊界」就像上面的同步塊一樣,只將需要的對象組合成聚合!

假設上面的產品和產品評論構成了一個聚合!那會發生什么事情呢?當A,B兩個用戶同時對這個商品進行評論,A先開始評論,此時就會鎖定該產品對象以及下面的所有評論,在A提交評論之前,B是無法操作這個產品對象的,顯然這是不合理的。


Respository VS DAO

在理解了聚合之后,就可以很容易的區分Respository與DAO了

  • DAO是技術手段,Respository是抽象方式
  • DAO只是針對對象的操作,而Respository是針對「聚合」的操作

【DAO的操作方式】

@Service @Transactional public class OrderService {public void createOrder(Order order,List<OrderDetail> orderDetailList) throws Exception {Long orderId = orderDao.save(order);for(OrderDetail detail : orderDetailList) {detail.setOrderId(orderId);orderDetailDao.save(detail);}}} }
  • 訂單和和訂單明細都有一個對應的DAO
  • 訂單和訂單明細的關系并沒有在對象之間得到體現

【Respository的操作方式】

// 訂單和訂單明細構成聚合 public clas Order{List<OrderDetail> itemLine; // 這里就保證了設計與編碼的一致性... }@Service @Transactional public class OrderService {public void createOrder(Order order) throws Exception {orderRespository.save(order);//ororder.save(); // 內部調用orderRespository.save(this);} }

當然,orderRespository的save方法中,可能還是數據庫相關操作,但也可能是NoSql操作甚至內存操作。

總結

以上是生活随笔為你收集整理的DDD - 聚合与聚合根_如何理解 Respository与DAO的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 波多野结衣大片 | 精品一区二区亚洲 | 最新视频 - 8mav | 亚洲精品www. | 欧美日韩三级在线观看 | 亚洲不卡视频在线 | 黄色美女一级片 | 中文字幕毛片 | 亚洲一区二区三区电影 | 超碰在线免费播放 | wwww日本60 | 都市激情校园春色 | 黄色片欧美 | 亚洲精品av在线 | 瑟瑟网站免费 | 亚洲裸体视频 | 亚洲一区国产 | 用力挺进新婚白嫩少妇 | 操亚洲| 久久久久久久亚洲av无码 | 日本小视频网站 | 午夜小电影 | 午夜影院黄 | 国产精选在线 | 黄色小说在线视频 | 被各种性器调教到哭vk | 日本在线免费播放 | 欧美午夜一区二区三区 | 中文字字幕在线中文乱码电影 | av啊啊 | 久久99精品国产.久久久久 | 久草中文在线视频 | 日韩性生交大片免费看 | 国产高清在线一区 | 亚洲男人的天堂在线视频 | 成年人免费在线观看视频网站 | 女女h百合无遮涩涩漫画软件 | a毛片在线观看 | 久久视频在线播放 | 一区二区三区四区在线免费观看 | 久久亚洲av无码精品色午夜麻豆 | 国产福利精品一区 | 国产精品网页 | 奇米四色7777 | 少妇高潮一区二区三区 | 男女无遮挡网站 | 老地方在线观看免费动漫 | 91美女片黄在线观看91美女 | 精品视频一区二区三区 | 国产高清av| 伊人网狼人 | www日本色 | 免费啪啪网 | 亚洲不卡在线视频 | 最新国产三级 | 婷婷激情六月 | 91亚洲精华国产精华精华液 | 中文字幕在线观看91 | 黑人性高潮 | 色图综合 | jzzijzzij亚洲成熟少妇在线观看 久久久精品人妻一区二区三区 | 欧美性生活在线视频 | 国产高清精品软件丝瓜软件 | 福利小视频在线播放 | 永久在线观看 | 久久亚洲AV无码 | 国产精品网站在线 | www夜夜操 | 国产精品欧美精品 | 5级黄色片 | 国产一区二区三区高清 | 日本美女影院 | 色鬼久久| 亚洲av综合色区无码另类小说 | 两女双腿交缠激烈磨豆腐 | 亚洲国产日韩精品 | 久久久免费精品视频 | 97潮色| 激情视频网站在线观看 | 亚洲免费色视频 | 黑人精品xxx一区一二区 | 久久久久97 | 中文天堂在线观看 | 一区二区日韩电影 | 夜夜骚av| 国产视频久久久久久 | 三级免费 | 亚洲日本色 | 国产一级做a爰片久久毛片男男 | 日韩av色| 亚洲石原莉奈一区二区在线观看 | 亚洲综合视频一区 | 超碰一区二区 | 日本免费福利视频 | 日本乱码视频 | 国产成a人亚洲精品 | 黄色一级片在线免费观看 | 天堂在线v | 特黄级 |