怎么在SpringData中使用JDBC實現DDD聚合-創新互聯

這篇文章將為大家詳細講解有關怎么在Spring Data中使用JDBC實現DDD聚合,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

創新互聯是一家集網站建設,曲沃企業網站建設,曲沃品牌網站建設,網站定制,曲沃網站建設報價,網絡營銷,網絡優化,曲沃網站推廣為一體的創新建站企業,幫助傳統企業提升企業形象加強企業競爭力。可充分滿足這一群體相比中小企業更為豐富、高端、多元的互聯網需求。同時我們時刻保持專業、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們為更多的企業打造出實用型網站。

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

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;
}

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

interface OrderRepository extends CrudRepository<PurchaseOrder, Long> {

 @Query("select count(*) from order_item")
 int countItems();
}

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

@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,它的所有項目也應該被刪除。

 …
 repository.delete(saved);

 assertThat(repository.count()).isEqualTo(0);
 assertThat(repository.countItems()).isEqualTo(0);
}

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

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,您可以建模多對多關系,如下所示:

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鼓勵這么做。

下面是測試:

@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實現DDD聚合就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

當前文章:怎么在SpringData中使用JDBC實現DDD聚合-創新互聯
轉載來于:http://m.kartarina.com/article38/dcpipp.html

成都網站建設公司_創新互聯,為您提供靜態網站App開發域名注冊網站制作網站營銷網站設計

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

成都定制網站網頁設計
主站蜘蛛池模板: AV无码精品一区二区三区| 久久久无码精品国产一区| 日韩精品无码视频一区二区蜜桃| 亚洲va成无码人在线观看| 最新中文字幕av无码专区| 国产在线无码制服丝袜无码| 日韩精品无码熟人妻视频| 无码视频免费一区二三区| 亚洲AV无码专区在线播放中文| 天堂一区人妻无码| 无码人妻久久一区二区三区| 在线无码午夜福利高潮视频| 无码成A毛片免费| 人妻少妇无码视频在线| 亚洲AV无码乱码在线观看代蜜桃| 免费无码AV一区二区| 亚洲AV无码国产剧情| 免费A级毛片无码视频| 亚洲国产精品无码久久久秋霞2| 成人免费无码大片A毛片抽搐色欲| 久久亚洲日韩看片无码| 国产成人精品无码片区在线观看| 日韩人妻无码免费视频一区二区三区| 久久99精品久久久久久hb无码| 国产精品va无码一区二区| 国产真人无码作爱免费视频| 国产成人无码午夜视频在线观看 | 亚洲va中文字幕无码久久不卡| 日本精品人妻无码免费大全| 亚洲精品无码久久毛片波多野吉衣| 中文字幕丰满乱孑伦无码专区| 国产精品午夜无码体验区| 无码一区二区三区中文字幕| 无码射肉在线播放视频| 人妻少妇精品无码专区漫画| 亚洲AV成人无码网天堂| 免费无码又爽又刺激高潮| 67194成是人免费无码| 国产精品无码翘臀在线观看| 特级无码a级毛片特黄| 成在线人免费无码高潮喷水|