如何从自定义实现中引用“正常”弹簧数据存储库?
Posted
技术标签:
【中文标题】如何从自定义实现中引用“正常”弹簧数据存储库?【英文标题】:How to reference the 'normal' spring data repo from a custom implementation? 【发布时间】:2015-04-06 07:55:10 【问题描述】:我想用自定义实现扩展JpaRepository
,所以我添加了一个MyRepositoryCustom
接口和一个扩展此接口的MyRepositoryImpl
类。
有没有办法在我的自定义类中从JpaRepository
调用方法?
注意:这也是对 https://***.com/a/11881203/40064 的评论,但我认为这很常见,值得单独提问。
【问题讨论】:
我们通常建议不要扩展JpaRepository
,因为它会暴露客户通常不应该知道的商店特定 API。
我同意,我尽可能使用CrudRepository
,但这是一个迁移项目,所以有时我需要来自JpaRepository
的一些东西
【参考方案1】:
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 为该依赖项创建一个延迟初始化的代理即使它首先为MyRepository
创建一个实例。在自定义方法的实现中,您可以使用 ….get()
-method 访问实际的 bean。
Provider
是来自@Inject
JSR 的接口,因此是标准化接口,需要对该 API JAR 的额外依赖。如果您只想坚持使用 Spring,您可以使用 ObjectFactory
作为替代接口,但会获得完全相同的行为。
【讨论】:
我猜MyCustomRepository
应该是 MyRepositoryCustom
? Repository
也接受 2 个参数。我很清楚你知道这一点,但它会让其他偶然发现它的人的答案更完整:)
我已经按照您的预期修复了类型签名。 Manish 的回答没有退路,这是一个完全不同的目的。他的答案针对所有存储库(您表示您不想要,让我首先添加我的答案)。另外,在我的用例中,您可以访问整个存储库,而不仅仅是 SimpleJpaRepository
。
是否可以通过允许将MyRepositoryImpl
抽象化来支持这一点?我不知道 Spring Data 是否可以采用该抽象类并将 CrudRepo 的实现“添加”到它?它将避免使用Provider
的解决方法
谢谢奥利弗。这应该是官方文档的一部分,我从几个月开始就一直在寻找这个。
Provider在什么包里?每个库都有自己的 Provider 类。是这个 javax.inject.Provider 吗?【参考方案2】:
文档中标题为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
中调用。
【讨论】:
我不想将此添加到我的所有存储库中。这只适用于一个存储库吗? 是的,请参考我链接到的上面的部分。以上是关于如何从自定义实现中引用“正常”弹簧数据存储库?的主要内容,如果未能解决你的问题,请参考以下文章