Elasticsearch和Jpa整合报错BeanDefinitionOverrideException: Invalid bean definition with name

报错

org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'ESRepository' defined in com.live.repository.elasticsearch.ESRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot register bean definition [Root bean: class [org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean]; 
scope=; 
abstract=false; 
lazyInit=true;
autowireMode=0; 
dependencyCheck=0; 
autowireCandidate=true;
primary=false; 
factoryBeanName=null; 
factoryMethodName=null; 
initMethodName=null; 
destroyMethodName=null; 
defined in com.live.repository.elasticsearch.ESRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration] for bean 'ESRepository': There is already [Root bean: class [org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactoryBean]; 
scope=; 
abstract=false; 
lazyInit=false; 
autowireMode=0; 
dependencyCheck=0; 
autowireCandidate=true; 
primary=false; 
factoryBeanName=null; 
factoryMethodName=null; 
initMethodName=null; 
destroyMethodName=null; 
defined in com.live.repository.elasticsearch.ESRepository defined in @EnableElasticsearchRepositories declared on ElasticsearchRepositoriesRegistrar.EnableElasticsearchRepositoriesConfiguration] bound. 

代码

Model

package com.live.model;

import lombok.Data;

import javax.persistence.*;


@Data
@Entity
@Document(indexName="es_test")
@Table(name = "test_user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "test_name",unique = true)
    private String name;

    @Column(name = "test_password")
    private String password;

}


Elasticsearch的repository

package com.live.repository.elasticsearch;

import com.live.model.User;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface ESRepository extends ElasticsearchRepository<User,Integer> {
}

JPA的Repository

package com.live.repository.jpa;

import com.live.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MyJPARepository extends JpaRepository<User,Integer> {
}

可以看到在同一Model中同时带有@Entity和@Document注解
而Spring Data就是通过区分这两个注解
来识别是使用JpaRepository还是ElasticsearchRepository的

以下是官网在这部分的描述(这是翻译后的文档,完整文档请进入我的博客查看)

interface PersonRepository extends Repository<Person, Long> {}

@Entity
class Person {}

interface UserRepository extends Repository<User, Long> {}

@Document
class User {}

PersonRepository引用Person, Person被JPA @Entity注解,所以这个存储库显然属于Spring Data JPA。UserRepository引用User, User用Spring Data MongoDB的@Document注解注解。

下面这个糟糕的示例显示了使用带有混合注解的类的存储库

例9. 使用带有混合注解的类的存储库定义

interface JpaPersonRepository extends Repository<Person, Long> {}

interface MongoDBPersonRepository extends Repository<Person, Long> {}

@Entity
@Document
class Person {}

此示例显示了同时使用JPA和Spring Data MongoDB批注的域类。 它定义了两个存储库,JpaPersonRepository和MongoDBPersonRepository。 一个用于JPA,另一个用于MongoDB。 Spring Data不再能够区分存储库,这导致不确定的行为。

Repository type detailsdistinguishing domain class annotations 以确定特定Spring数据模块的存储库候选。可以在同一域类型上使用多个特定于持久性技术的注解,并支持跨多个持久性技术重用域类型。但是,Spring Data随后就不能再确定绑定存储库的惟一模块。

区分存储库的最后一种方法是确定存储库基包的范围。基本包定义扫描存储库接口定义的起始点,这意味着存储库定义位于适当的包中。默认情况下,注解驱动的配置使用配置类的包。必须使用基于xml的配置中的基本包base package in XML-based configuration

下面的示例显示了基本包的注解驱动配置

例10. 基本包的注解驱动配置

@EnableJpaRepositories(basePackages = "com.acme.repositories.jpa")
@EnableMongoRepositories(basePackages = "com.acme.repositories.mongo")
class Configuration {}

解决办法

将model写为两个,放入不同的包下,分别使用 @Entity@Document注解
如:包为com.live.model

package com.live.model;

import lombok.Data;

import javax.persistence.*;


@Data
@Entity
@Table(name = "test_user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "test_name",unique = true)
    private String name;

    @Column(name = "test_password")
    private String password;

}


包为:com.live.document

package com.live.document;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;


@Data
@Document(indexName = "es_test")
public class User {

    @Id
    private Integer id;
    private String name;
    private String password;

}


这样ElasticsearchRepository和JapRepository就互不影响了


版权声明:本文为weixin_44216706原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。