Spring - 找到多个Spring Data模块,进入严格的存储库配置模式

ROZ*_*OZZ 15 spring-data spring-data-jpa spring-data-redis spring-boot spring-data-elasticsearch

我使用Spring Boot 2和Spring Data,Spring-Data-Elastisearch和Spring-data-Redis(用于http会话).当我启动应用程序.我收到了

2017-10-29 17:38:33.376  INFO 18625 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2017-10-29 17:38:33.451  INFO 18625 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2017-10-29 17:38:33.461  INFO 18625 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2017-10-29 17:38:33.768  INFO 18625 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2017-10-29 17:38:33.783  INFO 18625 --- [  restartedMain] .RepositoryConfigurationExtensionSupport : Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.ecommerce.core.repository.elastic.ProductElasticSearchRepository.
2017-10-29 17:38:33.787  INFO 18625 --- [  restartedMain] .RepositoryConfigurationExtensionSupport : Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.ecommerce.core.repository.jpa.UserRepository.
2017-10-29 17:38:33.790  INFO 18625 --- [  restartedMain] .RepositoryConfigurationExtensionSupport : Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.ecommerce.core.repository.jpa.catalog.CategoryJsonWrapperRepository.
2017-10-29 17:38:33.793  INFO 18625 --- [  restartedMain] .RepositoryConfigurationExtensionSupport : Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.ecommerce.core.repository.jpa.catalog.CategoryRepository.
2017-10-29 17:38:33.794  INFO 18625 --- [  restartedMain] .RepositoryConfigurationExtensionSupport : Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.ecommerce.core.repository.jpa.catalog.ProductRepository.
Run Code Online (Sandbox Code Playgroud)

在我的App.java文件中,我有以下几行(应避免歧义)

@EnableJpaRepositories(basePackages = {"com.ecommerce.core.repository.jpa"})
@EnableElasticsearchRepositories(basePackages= {"com.ecommerce.core.repository.elastic"})
@EnableRedisRepositories(basePackages = {"org.springframework.data.redis.connection.jedis"})
Run Code Online (Sandbox Code Playgroud)

每个spring数据存储库都针对其作业接口(主要是JpaRepository和ElasticsearchCrudRepository之一)进行扩展

我读了这篇文章 - https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.multiple-modules.types,正如你所看到的,一切都应该没有问题.

Mik*_*048 31

抱歉回答得太晚了,但我认为目前的答案已经无法解释发生这种情况的实际、深层原因。让我解释一下一切,以便让您了解其内涵(做好准备,这将是相当长且全面的)。如果您正在寻找简单的解决方案,请转到我的答案的底部:

首先,spring data 作为一个通用模块(忘记特定的模块,如 spring data jpa 或 spring data redis),具有接口的层次结构。它从Repository开始,然后是CrudRepository,之后是PagingAndSortingRepository。我不会详细介绍它们之间的区别,这不是现在的重点。重要的是 -这个接口与特定的持久性存储完全隔离,只是因为它们在技术上驻留在单独的 JAR 中,该 JAR 立即随任何特定的 spring 数据实现一起提供(称为spring-data-commons,请参阅官方文档,如果你感兴趣)

我的意思是 - 你可以使用 MongoDB 的 Spring 数据模块。为了利用 spring data mongodb,您通常会做什么:对,扩展 CrudRepository、Repository 或 MongoRepository。这是非常重要的 - 从 spring-data 的角度来看,如果您通过扩展 Repository 或 CrudRepository 创建自己的接口,并且无论如何都没有标记目标存储库实体(我将在答案末尾解释),那么 Spring 基本上会尝试自己找出这个神奇的方法:findById、deleteById等到底是如何实现的,因为显然它们的实现在Mongo和JPA中会有所不同。考虑到这一点,请继续阅读。

问题是 - spring究竟如何确定自定义接口必须实现的方式?嗯,Spring 内部有一个抽象,称为RepositoryFactoryBeanSupport。这是实际参与从自定义存储库创建 Bean 的事情。现在让我们做一个实验:尝试将 spring data jdbc starter 和 spring data mongodb starter 添加到您的项目中。您会注意到,在您的类路径中,有2 个 RepositoryFactoryBeanSupport 的不同实现

  1. JdbcRepositoryFactoryBean(来自spring data jdbc starter)
  2. MongoRepositoryFactoryBean(来自spring data mongo starter)

然后,假设我有一个实体,如下所示:

@AllArgsConstructor
@NoArgsConstructor
@Data
public class Customer {

    @Id
    private Long id;

    @Column("firstname")
    private String firstName;

    @Column("phone")
    private String phone;
}
Run Code Online (Sandbox Code Playgroud)

另请注意: Id 和 Column 注释实际上是 Spring 数据注释,而不是 JPA

然后我们定义一个接口(简单的dao接口):

public interface CustomerCRUDRepository extends CrudRepository<Customer, Long> {
    int countByFirstName(String firstName);
}
Run Code Online (Sandbox Code Playgroud)

现在,在某处注入 CustomerCRUDRepository 类型的 bean。只要尝试引导应用程序 - 你就会失败。为什么?让我们一起调查一下日志:

RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!

RepositoryConfigurationDelegate : Bootstrapping Spring Data JDBC repositories in DEFAULT mode

RepositoryConfigurationExtensionSupport : Spring Data JDBC - Could not safely identify store assignment for repository candidate interface com.example.springdatajdbc.repositories.CustomerCRUDRepository
Run Code Online (Sandbox Code Playgroud)

与您的问题相同的例外,不是吗?最后让我们来分解一下。现在让我终于回答一下这个问题。

那么,为什么会出现这个异常:

当您在项目中拥有多个 spring-data 模块时,尝试为特定实体创建一个接口,该接口没有使用特定于持久性技术的注释(例如 javax.persistence 中的 @Entity 或 mongo 中的 @Document ),您命名它),通过从 spring-data-commons 模块(即 Repository 或 CrudRepository)扩展接口 - 这根本不起作用,因为 spring 基本上不知道您的实体到底与哪个数据存储相关联。是 MongoDb 吗?或者是JPA?还是卡桑德拉?- 不可能以这种方式确定,请参阅官方文档。另一方面,当类路径中只有一个 spring 数据模块时 - spring 可以自行总结所有内容,因为它不是含糊的。

你可以做什么来解决它:

  1. 扩展特定于技术的存储库。例如,如果您希望实体 A 与 PostgreSQL 关联,则不要使用 CrudRepository - 使用 JpaRepository。如果希望实体B与Redis关联,则使用RedisRepository等。

  2. 使用注释来注释您的实体,表明它与特定数据存储的隶属关系。@Entity、@Document、@Table 等。

我希望,现在一切都清楚了。我真的尽力向你解释了。感谢您的阅读,祝您有美好的一天!


Nik*_*hil 6

由于您明确启用特定软件包上的存储库。您可以将其包含在 application.properties 中以避免这些错误:

spring.data.redis.repositories.enabled=false
Run Code Online (Sandbox Code Playgroud)

您也可以对其他存储库执行相同操作。如果遇到类似错误:

spring.data.elasticsearch.repositories.enabled=false
spring.data.jpa.repositories.enabled=false
Run Code Online (Sandbox Code Playgroud)

参考:https : //docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html


Han*_*ank 5

你的配置没问题。问题是由RedisRepositoriesAutoConfiguration. 它EnableRedisRepositories仅使用默认配置重复注册,默认配置为空basePackages.

要解决该问题,您可以RedisRepositoriesAutoConfiguration通过以下方式排除:

@SpringBootApplication(
        exclude = { RedisRepositoriesAutoConfiguration.class }
)
public class MySpringBootApp {

}
Run Code Online (Sandbox Code Playgroud)


Igo*_*lac 5

在其中一个项目中,我们收到了如下消息:

Spring Data LDAP - Could not safely identify store assignment for repository candidate interface com.company.xxx.EncryptionKeyRepository.
Run Code Online (Sandbox Code Playgroud)

解决方案是将这一行添加到application.properties文件中

spring.data.ldap.repositories.enabled=false
Run Code Online (Sandbox Code Playgroud)

这是针对 Spring Data LDAP 的。我想其他 Spring Data 组件也是类似的。


Ale*_*der 0

也许已经太晚了,但无论如何。它只是一条信息性消息,可帮助您了解 Spring Data 模块的配置方式。例如:

 INFO 87518 --- [main] .RepositoryConfigurationExtensionSupport : 
     Spring Data JPA - Could not safely identify store assignment for repository 
          candidate interface com.some.package.MyRepository.
Run Code Online (Sandbox Code Playgroud)

意味着 Spring Data JPA 模块将跳过 MyRepository 类并且不会使用它。