国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 使用Spring Data JDBC實現DDD聚合的示例代碼

使用Spring Data JDBC實現DDD聚合的示例代碼

2021-06-02 14:14解道 Java教程

這篇文章主要介紹了使用Spring Data JDBC實現DDD聚合的示例代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

本文討論了spring data jdbc如何實現ddd中聚合根存儲的設計思路,其中主要討論了是不是每個實體都需要一個對應數據表,這種問題需要根據具體情況而定。

spring data jdbc比jpa更容易理解,比如對象引用特性會很有趣。作為第一個示例,請考慮以下領域模型:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class purchaseorder {
 
 private @id long id;
 private string shippingaddress;
 private set<orderitem> items = new hashset<>();
 
 void additem(int quantity, string product) {
  items.add(createorderitem(quantity, product));
 }
 
 private orderitem createorderitem(int quantity, string product) {
 
  orderitem item = new orderitem();
  item.product = product;
  item.quantity = quantity;
  return item;
 }
}
class orderitem {
 int quantity;
 string product;
}

另外,考慮如下定義的存儲庫:

?
1
2
3
4
5
interface orderrepository extends crudrepository<purchaseorder, long> {
 
 @query("select count(*) from order_item")
 int countitems();
}

如果使用商品創建訂單,希望所有商品都能保存:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@autowired orderrepository repository;
 
@test
public void createupdatedeleteorder() {
 
 purchaseorder order = new purchaseorder();
 order.additem(4, "captain future comet lego set");
 order.additem(2, "cute blue angler fish plush toy");
 
 purchaseorder saved = repository.save(order);
 
 assertthat(repository.count()).isequalto(1);
 assertthat(repository.countitems()).isequalto(2);
 

此外,如果刪除purchaseorder,它的所有項目也應該被刪除。

?
1
2
3
4
5
6
 repository.delete(saved);
 
 assertthat(repository.count()).isequalto(0);
 assertthat(repository.countitems()).isequalto(0);
}

如果我們需要一個語法上相同但語義上不同的關系呢?上述訂單中包含訂單條目orderitem , 當訂單刪除時,包含的orderitem 都刪除了,但是看看看看下面案例,也是使用包含一個集合:

?
1
2
3
4
class book {
 // …
 set<author> authors = new hashset<>();
}

當書籍絕版時,將book刪除。所有的作者author也都丟失了。這當然不是你想要的,因為一些作者可能也寫過其他書。

怎么辦?

讓我們看一看存儲庫實際存在的內容。這與一遍又一遍的問題密切相關:是否應該在jpa中為每個表創建一個存儲庫?

而正確和權威的答案是“不”。存儲庫持久聚合并加載聚合。聚合是一個包含各種對象的群,它應始終保持一致。此外,它應始終保持(和加載)在一起。它有一個對象,稱為聚合根,它是唯一允許外部訪問或引用聚合內部的代理或管理者。聚合根是傳遞給存儲庫的,以便持久化聚合里面的對象群。

這提出了一個問題:spring data jdbc如何確定什么是聚合的一部分,哪些不是?答案非常簡單:非瞬態non-transient 引用都是聚合的一部分,這樣就可從聚合根到達聚合內部所有內容。

orderitem實例是聚合的一部分,因此被刪除; author正好相反,實例不是book聚合的一部分,因此不應刪除。所以不應該從book內部去引用那些作者author對象。

問題解決了。好吧,......不是真的。我們仍然需要存儲和訪問有關book和author之間的關系信息。答案可以在領域驅動設計(ddd)中找到,它建議使用id而不是直接引用。這適用于各種多對x關系。

如果多個聚合引用同一個實體,則該實體不能成為引用它的多個聚合的一部分,因為它只能是其中一個聚合的一部分。因此,任何“多對一”和“多對多”關系都只能通過引用id來建模實現了。

這樣可以實現多種目的:

1. 清楚地表示了聚合的邊界。

2. 還完全解耦(至少在應用程序的領域模型中)所涉及的兩個聚合。

3. 這種分離可以用不同的方式在數據庫中表示:

a. 以通常的方式保留數據庫,包括所有外鍵。這意味著必須確保以正確的順序創建和保留聚合。

b. 使用延遲約束,僅在事務的提交階段進行檢查。這可能會提高吞吐量。它還編纂了最終一致性的版本,其中“最終”與交易結束相關聯。這也允許引用從未存在的聚合,只要它僅在事務期間發生。這對于避免大量基礎結構代碼只是為了滿足外鍵和非空約束可能是有用的。

c. 完全刪除外鍵,實現真正的最終一致性。

d. 將引用的聚合保留在不同的數據庫中,甚至可能是no sql存儲。

無論如何,即使spring data jdbc也鼓勵應用模塊化。此外,如果嘗試遷移一個具有10年歷史的單體,你就會明白它的價值。

使用spring data jdbc,您可以建模多對多關系,如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class book {
 
 private @id long id;
 private string title;
 private set<authorref> authors = new hashset<>();
 
 public void addauthor(author author) {
  authors.add(createauthorref(author));
 }
 
 private authorref createauthorref(author author) {
 
  assert.notnull(author, "author must not be null");
  assert.notnull(author.id, "author id, must not be null");
 
  authorref authorref = new authorref();
  authorref.authorid = author.id;
  return authorref;
 }
}
 
@table("book_author")
class authorref {
 long authorid ;
}
 
class author {
 @id long id;
 string name;
}

請注意額外的類:authorref,它表示有關某個作者的book聚合的知識。它可能包含有關作者的其他聚合信息,然后實際上會在數據庫中重復。考慮到author數據庫可能與book數據庫完全不同,這會產生很多問題。

另請注意,authors是book 私有字段,authorref實例化在私有方法createauthorref中發生。因此聚合之外的任何內容都不能直接訪問它。spring data jdbc絕不需要這樣做,但ddd鼓勵這么做。

下面是測試:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@test
public void booksandauthors() {
 
 author author = new author();
 author.name = "greg l. turnquist";
 
 author = authors.save(author);
 
 book book = new book();
 book.title = "spring boot";
 book.addauthor(author);
 
 books.save(book);
 
 books.deleteall();
 
 assertthat(authors.count()).isequalto(1);
}

上述完成了我們設想功能:刪除書籍后,并沒有將書籍作者數據表數據全部刪除,雖然作者是書籍的一個私有字段。

總結一下:

spring data jdbc不支持多對一或多對多關系。要對這些進行建模,請使用id。

這鼓勵了領域模型的清晰模塊化。

通過類似的思路,避免雙向依賴。聚合內部的引用是從聚合根到元素。聚合之間的引用使用只在一個關聯方向上使用id表示。此外,如果需要反向導航,請在存儲庫中使用查詢方法。這樣能清楚確定哪個聚合負責維護引用。

banq注:是不是每個實體都需要一個對應數據表?根據具體情況,order和orderitem之間生命周期是一致的,刪除訂單,訂單條目也沒有存在意義;而book和author則不是生命周期一致的,book可能是當前有界上下文的聚合根,而author是另外一個有界上下文如作者管理系統的聚合根,如果刪除book同時,也將author刪除,其實是不符合要求的,這時候應該將author作為值對象看待,author的id就是一個值,然后建立一個類authorref ,包含這個值,作為被book引用的對象,這樣就不是整個author實體聚合對象被book引用了。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://www.jdon.com/50192

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产成人在线一区 | 国产一区二区三区在线免费观看 | 精品久久久久久亚洲精品 | 精品国产免费久久久久久尖叫 | 日韩在线成人av | 久久久www成人免费无遮挡大片 | 精品国产精品三级精品av网址 | 亚洲精品乱码 | 久久精品日产第一区二区三区 | 黄色免费网站 | 91视视频在线观看入口直接观看 | 日韩免费在线观看视频 | 亚洲一区二区三区在线 | 一本一道久久久a久久久精品91 | 欧美日韩视频在线观看免费 | 亚洲成人激情在线观看 | 日韩午夜 | 狠狠ri| 久久久久无码国产精品一区 | 亚洲一区 中文字幕 | 69久久| 国产精品毛片久久久久久久明星 | 综合久久精品 | 久久福利 | 亚洲欧美综合精品久久成人 | 国产黄色大片 | 国产欧美在线 | 久久成人免费视频 | 亚洲在线一区二区 | 一大道一二三区不卡 | 国产精品视频久久 | 青青草91青娱盛宴国产 | 欧美欧美欧美 | 91视频免费在线看 | 中文字幕一区二区三区日韩精品 | 久久精品一| 99精品欧美一区二区蜜桃免费 | 91精品免费 | 国产做a爰片久久毛片a我的朋友 | 日本久久久久久 | 来个毛片 |