《Spring Data 官方文件》4.6 定製Spring Data倉庫實現
原文連結 譯者:zhanghTK
4.6 定製Spring Data倉庫實現
經常有必要為一少部分倉庫方法,提供一個定製的實現。Spring資料儲存庫允許您提供自定義儲存庫程式碼。並將其與通用CRUD整合抽象和查詢方法功能整合.
4.6.1 為單獨倉庫新增定製行為
為了定製功能豐富一個倉庫,你首先為定製功能定義一個介面和實現.使用你提供的倉庫介面來繼承自定義介面.
例20. 定製倉庫功能的介面
interface UserRepositoryCustom { public void someCustomMethod(User user); }
例21.定製功能的實現
class UserRepositoryImpl implements UserRepositoryCustom { public void someCustomMethod(User user) { // Your custom implementation } }
注意
類可以被找到最重要的一點是名字以Impl為字尾區別於倉庫的核心介面(見下文)
實現的本身沒有依賴Spring Data,可以是一個標準的Spring bean.所以你可以使用標準的依賴注入行為給其他bean注入引用,像JdbcTemplate,切面的一部分等等.
例22 修改你基本的倉庫介面
interface UserRepository extends CrudRepository<User, Long>, UserRepositoryCustom { // Declare query methods here }
讓你的標準倉庫介面繼承定製的.這樣做結合了CRUD和定製功能並使其可用於客戶端.
配置
如果你使用名稱空間配置,倉庫基本元件掃描類所在的包,根據掃描結果嘗試自動定製實現.這些類需要遵循命名規範:給倉庫介面名新增名稱空間元素屬性repositoryimpl-postfix.預設的字尾是Impl.
例23. 配置示例
<repositories base-package="com.acme.repository" /> <repositories base-package="com.acme.repository" repository-impl-postfix="FooBar"/>
第一個配置示例將查實查詢一個類com.acme.repository.UserRepositoryImpl來作為定製倉庫實現.而第二個示例將嘗試查詢com.acme.repository.UserRepositoryFooBar.
手動指定
上面的方法可以正常工作,只有當你的定製實現使用註解配置和自動注入,它將與其他Spring bean一樣被對待.如果你定製的實現需要特殊處理,你可以像描述那樣簡單定義一個bean並且命名它.基本元件將通過名稱引用手動定義的bean定義而不是它自己建立一個.
例24.手動指定定製實現
<repositories base-package="com.acme.repository" /> <beans:bean id="userRepositoryImpl" class="…"> <!-- further configuration --> </beans:bean>
4.6.2 為所有倉庫新增定製行為
當你希望把一個單獨的方法新增到你所有的倉庫介面中時,上面的方法就不可行了.為了新增定製到所有的倉庫,你首先新增一箇中間介面來定義共享的行為.
例25 定義共享定製行為介面
@NoRepositoryBean public interface MyRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> { void sharedCustomMethod(ID id); }
現在你的每個倉庫介面將繼承這個中間介面而不是Repository介面來包含功能的定義.接下來建立一箇中間介面的實現繼承持久化具體倉庫的基本類.這個類後面將作為倉庫代理的基本類.
例26 定製倉庫基本類
public class MyRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>implements MyRepository<T, ID> { private final EntityManager entityManager; public MyRepositoryImpl(JpaEntityInformation entityInformation,EntityManager entityManager) { super(entityInformation, entityManager); // Keep the EntityManager around to used from the newly introduced methods. this.entityManager = entityManager; } public void sharedCustomMethod(ID id) { // implementation goes here } }
警告
這個類需要有一個構造方法呼叫父類具體儲存倉庫工廠實現.萬一倉庫基礎類有多個構造,覆蓋包括一個EntityInformation加上儲存具體基本元件物件(例如一個EntityManager或者模板類)
Spring名稱空間下的預設行為為所有介面提供一個實現.這意味著如果在當前狀態下,Spring將建立一個MyRepository的例項.這當然不是被期望的,它只是作為一個用來定義實體的 Repository和真實倉庫介面的中間介面.為了排除一個繼承Repository的介面被當做一個倉庫介面被例項化,你可以給它使用@NoRepositoryBean(像上面)或者把它從配置中base-package移除.
最後一步是讓Spring Data基本元件識別到定製的倉庫基本類.在JavaConf使用註解@Enable…Repository的屬性repositoryBaseClass完成:
例27 使用JavaConfig配置一個定製倉庫基本類
@Configuration @EnableJpaRepositories(repositoryBaseClass = MyRepositoryImpl.class) class ApplicationConfiguration { … }
類似的屬性在XML名稱空間中也可以找到.
例28 使用XML配置一個定製倉庫基本類
<repositories base-package="com.acme.repository" base-class="….MyRepositoryImpl" />