【问题标题】:How to reference the 'normal' spring data repo from a custom implementation?如何从自定义实现中引用“正常”弹簧数据存储库?
【发布时间】:2015-04-06 07:55:10
【问题描述】:

我想用自定义实现扩展JpaRepository,所以我添加了一个MyRepositoryCustom 接口和一个扩展此接口的MyRepositoryImpl 类。

有没有办法在我的自定义类中从JpaRepository 调用方法?

注意:这也是对 https://stackoverflow.com/a/11881203/40064 的评论,但我认为这很常见,值得单独提问。

【问题讨论】:

  • 我们通常建议不要扩展 JpaRepository,因为它会暴露客户通常不应该知道的商店特定 API。
  • 我同意,我尽可能使用CrudRepository,但这是一个迁移项目,所以有时我需要来自JpaRepository的一些东西

标签: java spring-data spring-data-jpa


【解决方案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&lt;MyRepository&gt;,这将导致Spring 为该依赖项创建一个延迟初始化的代理即使它首先为MyRepository 创建一个实例。在自定义方法的实现中,您可以使用 ….get()-method 访问实际的 bean。

Provider 是来自@Inject JSR 的接口,因此是标准化接口,需要对该 API JAR 的额外依赖。如果您只想坚持使用 Spring,您可以使用 ObjectFactory 作为替代接口,但会获得完全相同的行为。

【讨论】:

  • 我猜 MyCustomRepository 应该是 MyRepositoryCustomRepository 也接受 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 中调用。

【讨论】:

  • 我不想将此添加到我的所有存储库中。这只适用于一个存储库吗?
  • 是的,请参考我链接到的上面的部分。
猜你喜欢
  • 2020-01-04
  • 2012-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-23
  • 1970-01-01
  • 2014-09-02
  • 1970-01-01
相关资源
最近更新 更多