如何在 Spring Boot 应用程序的同一个域类上同时使用 Spring Data JPA 和 Spring Data Elasticsearch 存储库?

Posted

技术标签:

【中文标题】如何在 Spring Boot 应用程序的同一个域类上同时使用 Spring Data JPA 和 Spring Data Elasticsearch 存储库?【英文标题】:How do you use both Spring Data JPA and Spring Data Elasticsearch repositories on the same domain class in a Spring Boot application? 【发布时间】:2015-12-28 23:45:54 【问题描述】:

我正在尝试在同一个域对象上同时使用 Spring Data JPA 和 Spring Data Elasticsearch,但它不起作用。

当我尝试运行一个简单的测试时,我得到了以下异常:

org.springframework.data.mapping.PropertyReferenceException: 否 找到类型 Person 的属性索引!在 org.springframework.data.mapping.PropertyPath.(PropertyPath.java:75) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.repository.query.parser.Part.(Part.java:76) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.repository.query.parser.PartTree$OrPart.(PartTree.java:235) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:373) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.repository.query.parser.PartTree$Predicate.(PartTree.java:353) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.repository.query.parser.PartTree.(PartTree.java:84) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.jpa.repository.query.PartTreeJpaQuery.(PartTreeJpaQuery.java:61) ~[spring-data-jpa-1.9.0.RELEASE.jar:na] 在 org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:95) ~[spring-data-jpa-1.9.0.RELEASE.jar:na] 在 org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:206) ~[spring-data-jpa-1.9.0.RELEASE.jar:na] 在 org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:73) ~[spring-data-jpa-1.9.0.RELEASE.jar:na] 在 org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.(RepositoryFactorySupport.java:408) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:206) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:251) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:237) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 在 org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92) ~[spring-data-jpa-1.9.0.RELEASE.jar:na] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] ... 43个常用框架 省略

它们在禁用任何一个时起作用。

该项目基于 Spring Boot 1.3.0.M5。

这是一个重现情况的示例项目:

https://github.com/izeye/spring-boot-throwaway-branches/tree/data-jpa-and-elasticsearch

【问题讨论】:

【参考方案1】:

Spring Data 中的存储库与数据源无关,这意味着 JpaRepositoryElasticsearchRepository 都汇总到 Repository 接口中。在这种情况下,Spring Boot 的自动配置将导致 Spring Data JPA 尝试为项目中的每个存储库配置一个 bean,该存储库继承任何 Spring Data Commons 基础存储库。

要解决此问题,您需要将 JPA 存储库和 Elasticsearch 存储库移动到单独的包中,并确保使用以下代码注释您的 @SpringBootApplication 应用程序类:

@EnableJpaRepositories @EnableElasticsearchRepositories

然后您需要为每个启用注释指定存储库的位置。这最终看起来像:

@SpringBootApplication
@EnableJpaRepositories("com.izeye.throwaway.data")
@EnableElasticsearchRepositories("com.izeye.throwaway.indexing")
public class Application 

    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    


然后您的应用程序将能够区分哪些存储库用于哪个 Spring Data 项目。

【讨论】:

感谢您提供详细信息。它给了我一个我选择的最终解决方案的提示。对我来说,使用includeFilters 比将它们移动到另一个包要好。 Spring Data 与数据源无关的特性非常好,但如果可能的话,Spring Data JPA 不扫描ElasticsearchRepository 接口会很好。 对我所做的事情感兴趣的人,请参阅github.com/izeye/spring-boot-throwaway-branches/commit/… 感谢 kenny-bastani 和 johnny-lim,我为你们投了票【参考方案2】:

你可以这样使用:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchCrudRepository.class))
@EnableElasticsearchRepositories(includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchCrudRepository.class))
public class DataConfiguration 
    ...

或者在 SpringBoot 中:

@SpringBootApplication
@EnableJpaRepositories(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchCrudRepository.class))
@EnableElasticsearchRepositories(includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchCrudRepository.class))
public class MyApplication 
    ...

【讨论】:

它应该在@EnableJpaRepositories 我们应该使用JpaRepository.class 对而不是ElasticsearchCrudRepository.class??? 因为我在@EnableJpaRepositories中使用exlude,所以。在 Jpa Repository 中,您不仅可以使用 JpaRepository.class

以上是关于如何在 Spring Boot 应用程序的同一个域类上同时使用 Spring Data JPA 和 Spring Data Elasticsearch 存储库?的主要内容,如果未能解决你的问题,请参考以下文章

启用跨域请求 Spring Boot

跨域不适用于 Spring Boot

Java Spring boot 2.0 跨域问题

Spring BootSpring Boot之跨域解决方案

在不同域中的 reactjs 和 spring boot 应用程序之间启用 CSRF

Java框架spring Boot学习笔记:Bean的作用域