简体   繁体   English

Spring Data-如何在存储库片段中重用存储库?

[英]Spring Data - How to reuse repository in repository fragment?

Update : the following is using Spring Boot 2.1.0 更新 :以下使用Spring Boot 2.1.0

I have a Spring Data repository and I am trying to provide some custom functionality to it, following the fragments example from the documentation . 我有一个Spring Data存储库,并尝试按照文档中片段示例为其提供一些自定义功能。

So I've added an extra interface to the repository: 因此,我向存储库添加了一个额外的接口:

public interface UserRepository extends JpaRepository<User, Long>, UserExtraLogic {
    User findByFirstNameAndLastName(String firstName, String lastName);
}

with this custom interface: 使用此自定义界面:

interface UserExtraLogic {
    void ensureHasAccess();
}

and its implementation: 及其实现:

class UserExtraLogicImpl implements UserExtraLogic {
    public void ensureHasAccess() {
    }
}

The problem is that I would like to be able to use my repositories inside UserExtraLogicImpl , so that I can reuse query methods like findByFirstNameAndLastName without having to write them by myself with EntityManager . 问题是我希望能够在UserExtraLogicImpl使用我的存储库,这样我就可以重用findByFirstNameAndLastName类的查询方法,而不必自己使用EntityManager编写。 So I tried this: 所以我尝试了这个:

class UserExrtaLogicImpl implements UserExtraLogic {
    @Autowired
    private UserRepository userRepository;
}

But then the application does not start. 但是随后应用程序无法启动。 I get a NullPointerException, but I think it's just Spring getting into a cycle trying to resolve these dependencies. 我得到了NullPointerException,但我认为这只是Spring进入尝试解决这些依赖关系的周期。

Is what I'm trying to do possible? 我想做的事可能吗? Is there another way to do this? 还有另一种方法吗?

You can lazily load your repository with ObjectFactory<T> (Spring concept) or Provider<T> (standard java api). 您可以使用ObjectFactory<T> (Spring概念)或Provider<T> (标准Java API)延迟加载存储库。

class UserExrtaLogicImpl implements UserExtraLogic {
    @Autowired
    private ObjectFactory<UserRepository> userRepository;

    public void soSomething() {
         userRepository().getObject().findById(xxx);
    }
}

I have the exactly the same code patterns and encounter the same problem in a recent project and I finally solve it by using @Lazy to lazy initialise UserRepository : 我有完全相同的代码模式,并且在最近的项目中遇到了相同的问题,最后通过使用@Lazy来懒惰初始化UserRepository来解决它:

class UserExrtaLogicImpl implements UserExtraLogic {

    @Lazy
    @Autowired
    private UserRepository userRepository;

}

Repositories enablement 仓库启用

From documentation 文档

If you're using Spring XML configuration, you should have this: 如果您使用的是Spring XML配置,则应具有以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jpa="http://www.springframework.org/schema/data/jpa"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/jpa
    http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

  <jpa:repositories base-package="com.acme.repositories" />

</beans>

If you're using Java configuration instead, you should have this: 如果您使用的是Java配置,则应具有以下配置:

@Configuration
@EnableJpaRepositories("com.acme.repositories")
class ApplicationConfiguration {

  @Bean
  EntityManagerFactory entityManagerFactory() {
    // …
  }
}

Repositories configuration 仓库配置

Also, you need to add @Repository annotation on your repositories: 另外,您需要在存储库上添加@Repository批注:

@Repository
public interface UserRepository extends JpaRepository<User, Long>, UserExtraLogic {
    User findByFirstNameAndLastName(String firstName, String lastName);
}

Explanation 说明

From documentation 文档

Using the repositories element looks up Spring Data repositories as described in “Creating Repository Instances” . 使用repositories元素可以按“创建存储库实例”中所述查找Spring Data存储 Beyond that, it activates persistence exception translation for all beans annotated with @Repository , to let exceptions being thrown by the JPA persistence providers be converted into Spring's DataAccessException hierarchy. 除此之外,它还为所有使用@Repository注释的bean激活持久性异常转换,以将JPA持久性提供程序引发的异常转换为Spring的DataAccessException层次结构。

Pay attention to this in documentation. 请在文档中对此加以注意。

Extending the fragment interface with your repository interface combines the CRUD and custom functionality and makes it available to clients.

When you extend your fragment interface, your final repository will include that as well. 扩展片段接口时,最终的存储库也将包括该接口。 That is the benift of it. 那是它的好处。 If you want to access original repository logic I can suggest you 3 methods. 如果您想访问原始存储库逻辑,我可以为您推荐3种方法。

  1. Add your query in your fragment and extend it in your repository. 在片段中添加查询,然后在存储库中扩展查询。 Then in your service method include an aggregated method. 然后在您的服务方法中包括一个聚合方法。 In that method write your logic. 用那种方法写你的逻辑。
  2. In your custom interface, inlude your repository and do not extend your custom interface in repository. 在自定义界面中,包括存储库,并且不要扩展存储库中的自定义接口。
  3. Use a decorator class. 使用装饰器类。 Delegate all the methods to repository and combine custom logic with repository. 将所有方法委托给存储库,并将自定义逻辑与存储库结合。

Do not include circular dependencies as it is not a good practise. 不要包括循环依赖,因为这不是一个好习惯。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM