报错
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 details 和distinguishing 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就互不影响了