21

我不太瞭解DDD存儲庫模式,但在Spring中的實現令我困惑。對Spring-Data DDD存儲庫模式感到困惑

public interface PersonRepository extends JpaRepository<Person, Long> { … } 

由於接口擴展JpaRepository(或MongoDBRepository ...),如果你從一個分貝另一個改變,你必須改變接口爲好。

對我來說,接口是有提供一些抽象,但在這裏它不是這麼多抽象...

你知道爲什麼Spring的數據的工作原理是什麼?

回答

11

你說得對,從外部的角度來看,接口是一個關於所有實現類的等價物的抽象概念。

而這正是發生在這裏:

  • JpaRepository是所有JPA庫的公共視圖(所有不同的實體),而MongoDBRepository是所有MongoDB的實體相同。
  • 但JpaRepository和MongoDBRepository沒有任何共同之處,除了在有公用的超接口中定義的東西:

    • org.springframework.data.repository.PagingAndSortingRepository
    • org.springframework.data.repository .Repository

所以對我來說,它看起來正常。

如果您使用的是實現你的版本庫,然後,如果你希望能夠從一個JPA實現切換到基於文件的實現(抱歉,我無法想象這樣一個用例使用PagingAndSortingRepository或庫的類 - 反正 )。當然你的Repository實現應該實現正確的接口(JpaRepository,MongoDBRepository),具體取決於它是什麼。

+2

實際上,如果您在接口中知道存儲庫實現是給定類型的,爲什麼要使用接口呢?但我想你喜歡你很難做得更好...... – 2011-05-12 13:13:30

+0

我認爲/期望從RDBMS到面向文檔的商店的變化將需要在對象/域模型上進行重大更改。無論如何,*持久化抽象以某種方式泄漏*。總是。如果可以簡單地從JpaRepository更改爲MongoDBRepository而沒有對領域模型進行重大更改,那麼我會推測領域模型開始時並不複雜。沒有錯,因爲有些應用程序就是這樣。 – 2014-01-28 18:48:24

7

在這篇博客文章http://blog.springsource.com/2011/02/10/getting-started-with-spring-data-jpa/中很清楚地闡述了背後的推理。

定義這個接口有兩個目的:首先,通過擴展JpaRepository,我們得到了一堆通用的CRUD方法,這些方法允許保存帳號,刪除它們等等。其次,這將允許Spring Data JPA存儲庫基礎結構掃描該接口的類路徑併爲其創建一個Spring bean。

如果您不信任這麼靠近源代碼(雙關語意圖),那麼閱讀本文以及http://www.brucephillips.name/blog/index.cfm/2011/3/25/Using-Spring-Data-JPA-To-Reduced-Data-Access-Coding可能是一個好主意。

我不需要編碼的是PersonRepository接口的實現。 Spring將創建該接口的實現,並使PersonRepository bean可用於自動裝入我的Service類。 PersonRepository bean將擁有所有標準CRUD方法(這將是事務性的)並返回Person對象或Person對象的集合。所以通過使用Spring Data JPA,我節省了編寫自己的實現類。

+1

我不在乎實現。如果只需掃描存儲庫,爲什麼不擴展更常見的存儲庫接口?他們談論保存和刪除,我不知道有關mongoDB的更多信息,但我想我們也可以在mongoDB上執行這些操作...如果你公開像flush這樣的方法來服務,你是否依賴它們? – 2011-05-19 23:00:49

2

,直到春天數據的M2,我們需要用戶擴展JpaRepository由於以下原因:

  1. 類路徑掃描基礎設施只能拿起接口擴展爲一個可以使用Spring數據JPA和Spring數據接口並行的Mongo,並且他們都指向同一個軟件包,因此不清楚爲哪個存儲創建代理。然而,自RC1以來,我們只是將這一負擔留給開發人員,因爲我們認爲這是一個相當特殊的情況,只是使用Repository,CrudRepository等的好處超過了您在剛剛描述的角落案例中必須付出的努力。您可以在名稱空間中使用excludeinclude元素來獲得對此的更精細控制。
  2. 直到M2爲止,我們通過重新聲明CRUD方法並使用@Transactional註釋它們來將事務性應用於CRUD方法。這個決定反過來是由算法AnnotationTransactionAttributeSource用來查找交易配置。因爲我們希望通過在具體存儲庫接口中重新聲明CRUD方法並在其上應用@Transactional來爲用戶提供重新配置事務的可能性。對於RC1,我們決定實施一個自定義TransactionAttributeSource,以便能夠將註釋移回存儲庫CRUD實施。

長話短說,下面是它歸結爲:

由於RC1的就沒有必要再延長儲存庫特定接口,除了要 ...

  1. 使用List基於findAll(…)的訪問,而不是基於Iterable的更爲核心的存儲庫接口(儘管您可以簡單地重新聲明通用基接口中的相關方法以返回List s)
  2. 您想使用特定於JPA的方法,如saveAndFlush(…)等。

從RC1開始,通常您會對CRUD方法的暴露程度更加靈活,因爲您甚至只能擴展標記接口並選擇性地添加要公開的CRUD方法。由於底層實現仍然會實現所有的PagingAndSortingRepository的方法,我們仍然可以路由實例的電話:

public interface MyBaseRepository<T, ID extends Serializable> extends Repository<T, ID> { 

    List<T> findAll(); 

    T findOne(ID id); 
} 

public interface UserRepository extends MyBaseRepository<User, Long> { 

    List<T> findByUsername(String username); 
} 

在那個例子中,我們定義MyBaseRepository只露出findAll()findOne(…)(將被路由到該實例實施CRUD方法)以及具體的存儲庫爲兩個CRUD添加了查找方法。

有關該主題的更多詳細信息,請查閱reference documentation