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

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/113888.html

(0)
上一篇 2021年8月27日
下一篇 2021年8月27日

相关推荐

发表回复

登录后才能评论