如何从自定义实现中引用“普通”spring数据仓库?

时间:2015-02-06 08:14:13

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

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

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

注意:这也被问及对https://stackoverflow.com/a/11881203/40064的评论,但我认为这应该是一个单独的问题。

2 个答案:

答案 0 :(得分:13)

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() - 方法访问实际的bean。

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

答案 1 :(得分:1)

文档中标题为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扩展了SimpleJpaRepositoryJpaRepository的实现),JpaRepository中的所有方法都可以从ExtendedJpaRepositoryImpl调用。