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

时间:2018-11-15 14:59:47

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

更新:以下内容使用的是Spring Boot 2.1.0

我有一个Spring Data存储库,我尝试在fragments example from the documentation之后为其提供一些自定义功能。

因此,我向存储库添加了一个额外的接口:

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

具有此自定义界面:

interface UserExtraLogic {
    void ensureHasAccess();
}

及其实现:

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

问题是我希望能够在UserExtraLogicImpl中使用我的存储库,这样我就可以重用findByFirstNameAndLastName之类的查询方法,而不必自己用EntityManager编写它们。所以我尝试了这个:

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

但是随后应用程序无法启动。我收到了NullPointerException,但我认为只是Spring进入了一个尝试解决这些依赖关系的周期。

我想做的是可能的吗?还有另一种方法吗?

4 个答案:

答案 0 :(得分:1)

您可以使用ObjectFactory<T>(Spring概念)或Provider<T>(标准Java API)延迟加载存储库。

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

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

答案 1 :(得分:1)

我拥有完全相同的代码模式,并且在最近的项目中遇到了相同的问题,最后我通过使用@Lazy来延迟UserRepository的初始化来解决了这个问题:

class UserExrtaLogicImpl implements UserExtraLogic {

    @Lazy
    @Autowired
    private UserRepository userRepository;

}

答案 2 :(得分:0)

启用存储库

来自documentation

如果您使用的是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>

如果您使用的是Java配置,则应该具有以下内容:

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

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

存储库配置

此外,您需要在存储库中添加@Repository批注:

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

说明

来自documentation

  

使用repositories元素将Spring Data存储库查找为   “Creating Repository Instances”中描述。除此之外,它   为所有带注释的bean激活持久性异常转换   与@Repository一起使用,以使JPA抛出异常   持久性提供程序将转换为Spring的DataAccessException   层次结构。

答案 3 :(得分:0)

请在文档中注意这一点。

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

扩展片段接口时,最终的存储库也将包括该接口。那是它的好处。如果您想访问原始存储库逻辑,我可以为您推荐3种方法。

  1. 在片段中添加查询,然后在存储库中扩展它。然后在您的服务方法中包括一个聚合方法。用这种方法编写您的逻辑。
  2. 在自定义界面中,包含存储库,请勿扩展存储库中的自定义界面。
  3. 使用装饰器类。将所有方法委托给存储库,并将自定义逻辑与存储库结合。

不要包括循环依赖,因为这不是一个好习惯。