原文链接 译者: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