1. 程式人生 > >《Spring Data 官方文件》4.6 定製Spring Data倉庫實現

《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" />