[SpringBoot, ErrorReport] JPARepository와 ElasticSearchRepository 충돌 문제

Hyebin Lee·2022년 4월 20일
1

Springboot Error

목록 보기
1/1

참고한 링크

How do you use both Spring Data JPA and Spring Data Elasticsearch repositories on the same domain class in a Spring Boot application?
1-3) 스프링 @ComponentScan의 다양한 설정들 : basePackages, useDefaultFilters, includeFilters, excludeFilters, lazyInit

문제 상황

SpringBoot에서 SpringBoot ElasticSearch를 사용하려고 elasticsearch를 위한 repository를 생성한 후 extends ElasticSearchRepository를 하니까 오류가 발생했다.

프로젝트에서는 이미 다른 repository에서 JPARepository를 상속받아 사용하고 있는 상태였다.

에러 로그

The bean 'hashTagESRepository', defined in jpaproject.knockknock.elk.HashTagESRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration, could not be registered. A bean with that name has already been defined in jpaproject.knockknock.elk.HashTagESRepository defined in @EnableElasticsearchRepositories declared on ElasticsearchRepositoriesRegistrar.EnableElasticsearchRepositoriesConfiguration and overriding is disabled.

원인

JPARepositoryElasticSearchRepository는 둘다 Repository 인터페이스를 상속받아 구현된 인터페이스이다.

따라서 auto configuration을 통해 SpringBoot 어플리케이션을 실행시킬 시 SpringBoot는 Spring Data JPA를 실행시켜 repository 인터페이스를 상속받아 구현된 repository bean들을 전부 찾아 configure 하려고 한다.

이것 때문에 elasticsearchRepository만 상속받은 repository에서도 jparepository와 충돌이 일어나는 것이다.

에러메세지를 다시 보면 역시나, elasticsearchrepository에서 이미 bean등록이 되었기 때문에 jparepository에서 등록이 안된다는 얘기를 하고 있다.

해결방안

1. 패키지 분리

이 문제를 해결하기 위해서는 JPARepository와 ElasticSearchRepository를 철저하게 분리해야 한다.
auto configuration에서 bean객체 등록을 위한 component scan은 패키지 단위로 이루어지기 때문에 각 repository를 쓸 코드들은 서로 다른 패키지에 담아주면 된다.

그리고 SpringBootApplication을 아래와 같이 설정한다.
@EnableJpaRepositories@EnableElasticsearchRepositories 어노테이션으로 각 repository가 어느 패키지에 있는지 지정해주는 것이다.

@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);
    }

}

2. include/excludeFilters

includeFilters는 특정 조건을 만족하는 클래스만 스캔하도록 지정한다.
아래 코드에서 사용한 FilterType.ASSIGNABLE_TYPE은 클래스를 기준으로 객체를 가져오는 코드이다. classes = {}형태로 여러 클래스를 지정할 수도 있다.
반대로 excludeFilters는 특정 조건을 만족하는 클래스는 스캔하지 않는 것을 의미한다.

@SpringBootApplication
@EnableJpaRepositories(
        excludeFilters = @ComponentScan.Filter(
                type = FilterType.ASSIGNABLE_TYPE, classes = HashTagESRepository.class))
@EnableElasticsearchRepositories(
        includeFilters = @ComponentScan.Filter(
                type = FilterType.ASSIGNABLE_TYPE, classes = HashTagESRepository.class))
public class KnockKnockApplication {

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

0개의 댓글