如何从自定义实现中引用 'normal' spring 数据存储库?
How to reference the 'normal' spring data repo from a custom implementation?
我想用自定义实现扩展 JpaRepository
,所以我添加了一个 MyRepositoryCustom
接口和一个扩展此接口的 MyRepositoryImpl
class。
有没有办法在我的自定义 class 中调用 JpaRepository
的方法?
注意:这也作为对 的评论提出,但我认为它很常见,值得单独提问。
文档中标题为 Adding custom behaviour to all repositories 的部分应该对您有所帮助。
例如(仅供参考):
public interface ExtendedJpaRepository<T, ID extends Serializable>
extends JpaRepository<T, ID> {
T findFirst();
T findLast();
}
public class ExtendedJpaRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID>
implements ExtendedJpaRepository<T, ID> {
public ExtendedJpaRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, entityManager);
}
public T findFirst() {
List<T> all = findAll();
return !all.isEmpty() ? all.get(0) : null;
}
public T findLast() {
List<T> all = findAll();
return !all.isEmpty() ? all.get(all.size() - 1) : null;
}
}
然后,根据上面链接的文档中给出的说明配置 ExtendedJpaRepositoryImpl
以供使用。
由于 ExtendedJpaRepositoryImpl
扩展了 SimpleJpaRepository
(它是 JpaRepository
的实现),JpaRepository
中的所有方法都可以从 ExtendedJpaRepositoryImpl
中调用。
tl;博士
要将核心存储库接口注入自定义实现,请将 Provider<RepositoryInterface>
注入自定义实现。
详情
实现该功能的核心挑战是正确设置依赖注入,因为您将要在要扩展的对象和扩展之间创建循环依赖。然而,这可以通过以下方式解决:
interface MyRepository extends Repository<DomainType, Long>, MyRepositoryCustom {
// Query methods go here
}
interface MyRepositoryCustom {
// Custom implementation method declarations go here
}
class MyRepositoryImpl implements MyRepositoryCustom {
private final Provider<MyRepository> repository;
@Autowired
public MyRepositoryImpl(Provider<MyRepository> repository) {
this.repository = repository;
}
// Implement custom methods here
}
这里最重要的部分是使用 Provider<MyRepository>
这将导致 Spring 为该依赖项创建延迟初始化的代理 即使它正在为 [=13 创建实例=]第一名。在自定义方法的实现中,您可以使用 ….get()
-method.
访问实际的 bean
Provider
是 @Inject
JSR 的一个接口,因此是一个标准化的接口,需要对 API JAR 的额外依赖。如果你只想坚持使用 Spring,你可以使用 ObjectFactory
作为替代接口,但会得到完全相同的行为。
我想用自定义实现扩展 JpaRepository
,所以我添加了一个 MyRepositoryCustom
接口和一个扩展此接口的 MyRepositoryImpl
class。
有没有办法在我的自定义 class 中调用 JpaRepository
的方法?
注意:这也作为对 的评论提出,但我认为它很常见,值得单独提问。
文档中标题为 Adding custom behaviour to all repositories 的部分应该对您有所帮助。
例如(仅供参考):
public interface ExtendedJpaRepository<T, ID extends Serializable>
extends JpaRepository<T, ID> {
T findFirst();
T findLast();
}
public class ExtendedJpaRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID>
implements ExtendedJpaRepository<T, ID> {
public ExtendedJpaRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, entityManager);
}
public T findFirst() {
List<T> all = findAll();
return !all.isEmpty() ? all.get(0) : null;
}
public T findLast() {
List<T> all = findAll();
return !all.isEmpty() ? all.get(all.size() - 1) : null;
}
}
然后,根据上面链接的文档中给出的说明配置 ExtendedJpaRepositoryImpl
以供使用。
由于 ExtendedJpaRepositoryImpl
扩展了 SimpleJpaRepository
(它是 JpaRepository
的实现),JpaRepository
中的所有方法都可以从 ExtendedJpaRepositoryImpl
中调用。
tl;博士
要将核心存储库接口注入自定义实现,请将 Provider<RepositoryInterface>
注入自定义实现。
详情
实现该功能的核心挑战是正确设置依赖注入,因为您将要在要扩展的对象和扩展之间创建循环依赖。然而,这可以通过以下方式解决:
interface MyRepository extends Repository<DomainType, Long>, MyRepositoryCustom {
// Query methods go here
}
interface MyRepositoryCustom {
// Custom implementation method declarations go here
}
class MyRepositoryImpl implements MyRepositoryCustom {
private final Provider<MyRepository> repository;
@Autowired
public MyRepositoryImpl(Provider<MyRepository> repository) {
this.repository = repository;
}
// Implement custom methods here
}
这里最重要的部分是使用 Provider<MyRepository>
这将导致 Spring 为该依赖项创建延迟初始化的代理 即使它正在为 [=13 创建实例=]第一名。在自定义方法的实现中,您可以使用 ….get()
-method.
Provider
是 @Inject
JSR 的一个接口,因此是一个标准化的接口,需要对 API JAR 的额外依赖。如果你只想坚持使用 Spring,你可以使用 ObjectFactory
作为替代接口,但会得到完全相同的行为。