对于最新的稳定版本,请使用 Spring Data Commons 3.3.1! |
对于最新的稳定版本,请使用 Spring Data Commons 3.3.1! |
Spring Data 提供了各种选项来创建查询方法,只需很少的编码。 但是,当这些选项不符合您的需求时,您也可以为存储库方法提供自己的自定义实现。 本节介绍如何执行此操作。
自定义单个存储库
要使用自定义功能扩充存储库,必须首先定义自定义功能的片段接口和实现,如下所示:
interface CustomizedUserRepository {
void someCustomMethod(User user);
}
class CustomizedUserRepositoryImpl implements CustomizedUserRepository {
public void someCustomMethod(User user) {
// Your custom implementation
}
}
类名中与片段接口对应的最重要的部分是后缀。Impl |
实现本身不依赖于 Spring Data,可以是常规的 Spring Bean。
因此,您可以使用标准的依赖注入行为来注入对其他 bean(例如 a)、参与方面等的引用。JdbcTemplate
然后,您可以让您的仓库接口扩展 fragment 接口,如下所示:
interface UserRepository extends CrudRepository<User, Long>, CustomizedUserRepository {
// Declare query methods here
}
使用存储库接口扩展片段接口将 CRUD 和自定义功能相结合,并使其可供客户端使用。
Spring Data 存储库是通过使用构成存储库组合的片段来实现的。 片段是基本存储库、功能方面(如 QueryDsl)和自定义接口及其实现。 每次向存储库接口添加接口时,都会通过添加片段来增强组合。 基本存储库和存储库方面实现由每个 Spring Data 模块提供。
以下示例显示了自定义接口及其实现:
interface HumanRepository {
void someHumanMethod(User user);
}
class HumanRepositoryImpl implements HumanRepository {
public void someHumanMethod(User user) {
// Your custom implementation
}
}
interface ContactRepository {
void someContactMethod(User user);
User anotherContactMethod(User user);
}
class ContactRepositoryImpl implements ContactRepository {
public void someContactMethod(User user) {
// Your custom implementation
}
public User anotherContactMethod(User user) {
// Your custom implementation
}
}
以下示例显示了扩展的自定义存储库的接口:CrudRepository
interface UserRepository extends CrudRepository<User, Long>, HumanRepository, ContactRepository {
// Declare query methods here
}
存储库可以由多个自定义实现组成,这些自定义实现按其声明的顺序导入。 自定义实现的优先级高于基本实现和存储库方面。 此排序允许您覆盖基本存储库和 aspect 方法,并解决两个片段提供相同方法签名时的歧义问题。 存储库片段不限于在单个存储库接口中使用。 多个存储库可以使用片段接口,允许您在不同的存储库中重复使用自定义项。
以下示例显示了存储库片段及其实现:
save(…)
interface CustomizedSave<T> {
<S extends T> S save(S entity);
}
class CustomizedSaveImpl<T> implements CustomizedSave<T> {
public <S extends T> S save(S entity) {
// Your custom implementation
}
}
以下示例显示了使用上述存储库片段的存储库:
interface UserRepository extends CrudRepository<User, Long>, CustomizedSave<User> {
}
interface PersonRepository extends CrudRepository<Person, Long>, CustomizedSave<Person> {
}
配置
存储库基础结构尝试通过扫描它找到存储库的包下的类来自动检测自定义实现片段。
这些类需要遵循将后缀追加默认为 的命名约定。Impl
以下示例显示了使用默认后缀的存储库和为后缀设置自定义值的存储库:
-
Java
-
XML
@EnableJpaRepositories(repositoryImplementationPostfix = "MyPostfix")
class Configuration { … }
<repositories base-package="com.acme.repository" />
<repositories base-package="com.acme.repository" repository-impl-postfix="MyPostfix" />
前面示例中的第一个配置尝试查找一个名为充当自定义存储库实现的类。
第二个示例尝试查找 。com.acme.repository.CustomizedUserRepositoryImpl
com.acme.repository.CustomizedUserRepositoryMyPostfix
歧义的解决
如果在不同的包中找到多个具有匹配类名的实现,Spring Data 将使用 bean 名称来标识要使用的实现。
鉴于前面所示的以下两个自定义实现,将使用第一个实现。
它的 Bean 名称是 ,与片段接口 () 加上后缀 的 bean 名称匹配。CustomizedUserRepository
customizedUserRepositoryImpl
CustomizedUserRepository
Impl
class CustomizedUserRepositoryImpl implements CustomizedUserRepository {
// Your custom implementation
}
@Component("specialCustomImpl")
class CustomizedUserRepositoryImpl implements CustomizedUserRepository {
// Your custom implementation
}
如果用 注释接口,则 bean 名称 plus 与 中为存储库实现定义的 bean 名称 plus 匹配,并且使用它而不是第一个。UserRepository
@Component("specialCustom")
Impl
com.acme.impl.two
手动接线
如果您的自定义实现仅使用基于注释的配置和自动连线,则前面显示的方法效果很好,因为它被视为任何其他 Spring bean。 如果实现片段 Bean 需要特殊布线,可以声明 Bean 并按照上一节中描述的约定命名。 然后,基础结构通过名称引用手动定义的 Bean 定义,而不是自己创建一个 Bean 定义。 以下示例演示如何手动连接自定义实现:
-
Java
-
XML
class MyClass {
MyClass(@Qualifier("userRepositoryImpl") UserRepository userRepository) {
…
}
}
<repositories base-package="com.acme.repository" />
<beans:bean id="userRepositoryImpl" class="…">
<!-- further configuration -->
</beans:bean>
类名中与片段接口对应的最重要的部分是后缀。Impl |
自定义基本存储库
当您想要自定义基本存储库行为以使所有存储库都受到影响时,上一节中描述的方法需要自定义每个存储库接口。 若要改为更改所有存储库的行为,可以创建一个实现,用于扩展持久性技术特定的存储库基类。 然后,此类充当存储库代理的自定义基类,如以下示例所示:
class MyRepositoryImpl<T, ID>
extends SimpleJpaRepository<T, ID> {
private final EntityManager entityManager;
MyRepositoryImpl(JpaEntityInformation entityInformation,
EntityManager entityManager) {
super(entityInformation, entityManager);
// Keep the EntityManager around to used from the newly introduced methods.
this.entityManager = entityManager;
}
@Transactional
public <S extends T> S save(S entity) {
// implementation goes here
}
}
该类需要具有特定于存储库的工厂实现使用的超级类的构造函数。
如果存储库基类具有多个构造函数,请重写采用加 a 存储特定基础结构对象(如 或 模板类)的构造函数。EntityInformation EntityManager |
最后一步是使 Spring Data 基础结构了解自定义存储库基类。
在配置中,可以使用 执行此操作,如以下示例所示:repositoryBaseClass
-
Java
-
XML
@Configuration
@EnableJpaRepositories(repositoryBaseClass = MyRepositoryImpl.class)
class ApplicationConfiguration { … }
<repositories base-package="com.acme.repository"
base-class="….MyRepositoryImpl" />
该类需要具有特定于存储库的工厂实现使用的超级类的构造函数。
如果存储库基类具有多个构造函数,请重写采用加 a 存储特定基础结构对象(如 或 模板类)的构造函数。EntityInformation EntityManager |