![[Database/Error] spring에서 db 2개 사용할 때 생기는 Bean 문제 해결](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdVlBO%2FbtsISIis5kO%2FcbdjwkfqenbcBIanHStKok%2Fimg.png)
[Database/Error] spring에서 db 2개 사용할 때 생기는 Bean 문제 해결Database2024. 8. 3. 01:51
Table of Contents
728x90
반응형
1. 해결 방법
jpa가 repository를 탐색하지 않도록 하는 커스텀 어노테이션을 사용해서 Jpa의 @ComponentScan.Filter에 걸리도록해 리jpa리파지토리 등록을 자동으로 하지 않도록 했다.
QuerydslConfig
@EnableJpaRepositories(
basePackages = "진행하고 있는 프로젝트의 root폴더 ex: common.example",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = ExcludeFromJpaRepositories.class
)
)
@Configuration
public class QuerydslConfig {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
- @EnableJpaRepositories :
Jpa repository 를 활성화하고 지정된 패키지에서 repository interface를 스캔해서 spring 컨텍스트에 bean으로 등록한다. - basePackages :
Jpa repository를 스캔할 기본 패키지를 지정한다. 루트로 지정해서 프로젝트의 모든 리파지토리를 탐색하도록 했다. - excludeFilters :
특정 필터 조건에 맞는 리포지토리를 스캔에서 제외시킨다. - type : 필터 유형을 지정한다. 지금은 어노테이션을 사용한다. 필터 유형에서 사용할 수 있는 것으로는 아래 접은 글을 참고하자.
- classes : 제외할 class를 작성하면 된다. 위 코드처럼 1개만 설정할 수도 있고
classes = {ExcludedClass1.class, ExcludedClass2.class} 이런방식으로 여러개를 제외할 수도 있다.
나는 이건 너무 더러운거 같아서 어노테이션 방식을 사용했다.
type 필터 유형 종류
- ANNOTATION: 특정 애노테이션이 붙은 클래스를 필터링
- ASSIGNABLE_TYPE: 특정 클래스나 인터페이스를 상속받거나 구현한 클래스를 필터링
- ASPECTJ: AspectJ 표현식을 사용하여 필터링
- REGEX: 정규 표현식을 사용하여 필터링
- CUSTOM: 사용자 정의 필터를 사용하여 필터링
CustomAnotation
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcludeFromJpaRepositories {
}
다음은 jpa스캔을 하지 안도록하는 커스텀 어노테이션이다. 커스텀 어노테이션은 따로 정리하겠다.
맛있게 사용해보자!
@ExcludeFromJpaRepositories
public interface QuizRepository extends MongoRepository<QuizEntity, String>, CustomQuizRepository{
}
주의
이렇게 한번 필터를 걸어주게되면 jpa를 사용하는 리파지토리를 제외한 모든 리파지토리에 어노테이션을 걸어줘야한다.
ex : redis repository, mongo repository등이 있다. 안걸어주면 스캔해버린다.
2. 어떤 문제가 생긴걸까?
지금 내가 진행하고 있는 프로젝트의 의존성은 다음과 같다.
의존성
// postgreSQL
implementation group: 'org.postgresql', name:'postgresql', version: '42.2.19'
//jpa
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
// mongoDB
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
// QueryDsl
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
MongoConfig
@Configuration
public class MongoConfig {
@Value("${spring.data.mongodb.uri}")
private String uri;
@Value("${spring.data.mongodb.database}")
private String database;
@Bean
public MongoClient mongoClient() {
return MongoClients.create(uri);
}
@Bean
public MongoDatabaseFactory mongoDatabaseFactory(MongoClient mongoClient) {
return new SimpleMongoClientDatabaseFactory(mongoClient, database);
}
@Bean
public MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDatabaseFactory) {
return new MongoTemplate(mongoDatabaseFactory);
}
}
QuerydslConfig
@Configuration
public class QuerydslConfig {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
내가 직면한 에러
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'quizRepository', defined in darkoverload.itzip.csQuiz.repository.quiz.QuizRepository defined in @EnableMongoRepositories declared on MongoRepositoriesRegistrar.EnableMongoRepositoriesConfiguration, could not be registered. A bean with that name has already been defined in darkoverload.itzip.csQuiz.repository.quiz.QuizRepository defined in @EnableJpaRepositories declared on QuerydslConfig and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
Process finished with exit code 1
에러가 생긴 리파지토리
public interface QuizRepository extends MongoRepository<QuizEntity, String>{
}
이런상태로 MongoRepository를 이용해서 리파지토리를 구성하려고 했는데 이미 bean이 생성되었다는 것이다.
근데나는 이름이 겹치게 jpa리파지토리를 구성한적이 없는걸?
사실은...
전말은 이러했다. Spring Boot는 기본적으로 JPA설정을 우선시하기 떄문에 JPA리파지토리를 사용할때는 JPA를 우선 순위로 두게 되어 여러 Bean을 생성하지 않지만 MongoRepositoy를 사용하게된다면 우선순위로 생성된 JPA리파지토리 Bean이 먼저 생성되어 있어서 Bean이 이미 존재한다는 에러를 만드는 것이였다.
728x90
반응형
@코딩하는 자연대생 :: 자연대생도 코딩을 하고 싶어
Coding, Software, Computer Science 내가 공부한 것들 잘 이해했는지, 설명할 수 있는지 적는 공간