1.QueryDSL + single data source 인 경우
DataSourceConfiguration
- entityManagerFactory 생성 메서드
- 데이터소스 클래스를 생성하는 것이 주 내용이 아니기 때문에 entityManagerFactory 생성 메소드만 올린다.
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
@Qualifier("dataSource") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setPackagesToScan("com.example.rds.jpa.entity"); // entity 클래스가 있는 패키지 경로
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
entityManagerFactoryBean.setJpaPropertyMap(hibernateProperties());
return entityManagerFactoryBean;
}
QueryDslConfiguration
- @PersistenceContext로 DataSourceConfiguration에서 생성한 EntityManager를 주입.
- JPAQueryFactory 빈 등록
import com.querydsl.jpa.impl.JPAQueryFactory;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* The type Query dsl configuration.
*/
@Configuration
public class QueryDslConfiguration {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
JPAQueryFactory 사용
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;
import java.util.List;
import static com.example.db.jpa.entity.QTestInfo.testInfo;
/**
* The type Example Test info repository support.
*/
@Repository
public class ExampleTestRepositorySupport extends QuerydslRepositorySupport {
private final JPAQueryFactory queryFactory; // jPAQueryFactory 주입 받아 사용
/**
* Instantiates a new Example test repository support.
*
* @param queryFactory the query factory
*/
public ExampleTestRepositorySupport(JPAQueryFactory queryFactory) {
super(TestInfo.class);
this.queryFactory = queryFactory;
}
public List<TestInfo> findTestInfoListBySearch(long test_id) {
return queryFactory
.selectFrom(testInfo)
.where(testInfo.testId.eq(test_id))
.fetch();
}
}
2.QueryDSL + multi data source 인 경우
datasource가 2개이고 각각 entityManagerFactory 생성 메소드가 있는 경우에 위와 같이 그대로 구현하면 아래와 같은 오류가 발생한다.
Parameter 0 of method setEntityManager in org.springframework.data.jpa.repository.support.QuerydslRepositorySupport required a single bean, but 2 were found:
- org.springframework.orm.jpa.SharedEntityManagerCreator#0: defined by method 'createSharedEntityManager' in null
- org.springframework.orm.jpa.SharedEntityManagerCreator#1: defined by method 'createSharedEntityManager' in null
QueryDslConfiguration에서 entityManager에 객체 주입을 하는 과정에서 2개의 entityManager 팩토링 생성 메서드 중 어느 것으로 주입을 할지 몰라 생기는 오류다.
아래와 같이 수정한다.
DataSource1Configuration
/**
* Entity manager factory local container entity manager factory bean.
*
* @param dataSource the data source
* @return the local container entity manager factory bean
*/
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
@Qualifier("dataSource") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setPackagesToScan("com.example.rds.jpa.entity1");
entityManagerFactoryBean.setPersistenceUnitName("firstEntityManager"); // 영속성 객체 이름을 지정
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
entityManagerFactoryBean.setJpaPropertyMap(hibernateProperties());
return entityManagerFactoryBean;
}
DataSource2Configuration
/**
* Entity manager factory local container entity manager factory bean.
*
* @param dataSource the data source
* @return the local container entity manager factory bean
*/
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
@Qualifier("dataSource") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setPackagesToScan("com.example.rds.jpa.entity2");
entityManagerFactoryBean.setPersistenceUnitName("secondEntityManager"); // 영속성 객체 이름을 지정
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
entityManagerFactoryBean.setJpaPropertyMap(hibernateProperties());
return entityManagerFactoryBean;
}
QueryDslConfiguration
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Configuration
public class QueryDslConfig {
@PersistenceContext(unitName = "firstEntityManager")
private EntityManager firstEntityManager;
@PersistenceContext(unitName = "secondEntityManager")
private EntityManager secondEntityManager;
@Bean
public JPAQueryFactory firstJpaQueryFactory() {
return new JPAQueryFactory(firstEntityManager);
}
@Bean
public JPAQueryFactory secondJpaQueryFactory() {
return new JPAQueryFactory(secondEntityManager);
}
}
커스텀 QuerydslRepositorySupprt 클래스 구현 (상속으로)
- setter로 EntityManager를 지정
- SecondQuerydslRepositorySupprt 클래스도 마찬가지로 setter에 @PersistenceContext(unitName = "secondEntityManager") 라고 지정하여 구현하면 된다.
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Repository
public abstract class FirstQuerydslRepositorySupport extends QuerydslRepositorySupport {
/**
* Creates a new {@link QuerydslRepositorySupport} instance for the given domain type.
*
* @param domainClass must not be {@literal null}.
*/
public FirstQuerydslRepositorySupport(Class<?> domainClass) {
super(domainClass);
}
@Override
@PersistenceContext(unitName = "firstEntityManager")
public void setEntityManager(EntityManager entityManager) {
super.setEntityManager(entityManager);
}
}
실제 사용
- 위에서 구현한 커스텀 QuerydslRepositorySupprt을 상속받아 실세 QuertDSL을 사용하는 클래스를 구현한다.
- JPAQueryFactory 객체 주입할 때 @Qualifier 어노테이션으로 특정 빈을 지정
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import java.util.List;
import static com.example.db.jpa.entity.QTestInfo.testInfo;
/**
* The type Example Test info repository support.
*/
@Repository
public class ExampleTestRepositorySupport extends QuerydslRepositorySupport {
private final JPAQueryFactory queryFactory; // jPAQueryFactory 주입 받아 사용
/**
* Instantiates a new Example test repository support.
*
* @param queryFactory the query factory
*/
public ExampleTestRepositorySupport(@Qualifier("firstJpaQueryFactory")JPAQueryFactory queryFactory) {
super(TestInfo.class);
this.queryFactory = queryFactory;
}
public List<TestInfo> findTestInfoListBySearch(long test_id) {
return queryFactory
.selectFrom(testInfo)
.where(testInfo.testId.eq(test_id))
.fetch();
}
}
'개발 > Spring' 카테고리의 다른 글
Spring Boot 배포 WAR 에서 JAR 로 변경하기 (Spring Boot Embedded Tomcat 사용하기) (2) | 2022.04.13 |
---|---|
webflux + reactive redis cache 적용하기 (2) | 2021.08.23 |
Spring-Cloud-Data-Flow(SCDF)구축해보기 (4) | 2020.11.10 |