Closed ahnjunwoo-rsquare closed 2 months ago
멀티 데이터베이스 커넥션 설정시 아래의 transactionManager설정되어진 entitymanager xx.domain jpa 엔티티 모델이 존재하는데 계속 찾지 못한다는 이슈가 발생하는데 예를들어서
@Configuration @EnableJpaRepositories( basePackages = [ "xx.jpa.repository", ], entityManagerFactoryRef = "xxDbEntityFactory", transactionManagerRef = "xxDbTransactionManager", ) class CoreDbDataSourceConfig { @Bean(name = ["xxDbDataSource"]) @ConfigurationProperties(prefix = "spring.datasource.read") fun dataSource(): DataSource = DataSourceBuilder.create().build()
@Bean(name = ["xxDbEntityFactory"])
fun entityManagerFactory(
builder: EntityManagerFactoryBuilder,
@Qualifier("coreDbDataSource") dataSource: DataSource
): LocalContainerEntityManagerFactoryBean =
builder
.dataSource(dataSource)
.packages("xx.domain")
.persistenceUnit("core-db")
.build()
@Bean(name = ["xxDbTransactionManager"])
fun transactionManager(
@Qualifier("coreDbEntityFactory")
entityManagerFactory: EntityManagerFactory
): PlatformTransactionManager =
JpaTransactionManager(entityManagerFactory)
}
@Repository class ParsingTradeRepositorySupport( private val parsingTradeRepository: ParsingTradeRepository, ) { fun getParsingTrades( registrationId: Long, pageable: Pageable, ): Page<ParsingTrade?> { val pageParsingTrade = parsingTradeRepository.findPage(pageable) { select( entity(ParsingTrade::class), ).from( entity(ParsingTrade::class), ).whereAnd( path(ParsingTrade::registrationId).eq(registrationId), ).orderBy( Sorts.desc(Paths.path(ParsingTrade::listNo), nullOrder = Sort.NullOrder.LAST), ) } return pageParsingTrade } }
Caused by: org.hibernate.query.sqm.UnknownEntityException: Could not resolve root entity 'ParsingTrade' 엔티티를 찾지 못하는 이슈가 발생합니다. (xx.domain에 엔티티는 조회, jpa 조회같은 경우는 정상적으로 동작) 6시간 삽질중인데 예를들어 querydsl처럼 엔티티 매니저를 설정하는방법에 대해서 문의드립니다.
@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);
}
}
@ahnjunwoo-rsquare 안녕하세요.
Spring 환경에서 Multiple Datasource를 사용하는 방법은 총 2가지가 있습니다.
JpaRepository 없이 EntityManager만으로 Kotlin JDSL을 통해 생성된 쿼리를 실행할 수 있습니다. 아래 createQuery 메소드는 Spring Support에서 제공하는 확장함수로 jakarta 버전의 JPA를 사용하신다면 com.linecorp.kotlinjdsl.support.spring.data.jpa.extension
패키지를 통해 사용하실 수 있습니다.
val query = jpql {
select(
path(Author::authorId),
).from(
entity(Author::class),
join(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))),
).groupBy(
path(Author::authorId),
).orderBy(
count(Author::authorId).desc(),
)
}
val actual = entityManager.createQuery(query, context).setMaxResults(1).resultList.first()
JpaRepository가 참고하는 EntityManager는 Transaction을 통해 결정됩니다.
Spring이 주입해주는 EntityManager는 Proxy 객체로, 실제 사용될 때 다이나믹하게 주입됩니다. 주입될 EntityManager는 Transaction을 통해 결정되며, 현재 진행중인 Transaction의 TransactionManager가 가지고 있는 EntityManagerFactory로 EntityManager를 생성합니다.
이 방식을 이용해 JpaRepository 호출 전 Transactional 어노테이션에 Datasource에 따른 TransactionManager를 지정하는 것으로 쿼리가 실행될 Datasource를 선택할 수 있습니다.
@Repository
@Transactional("xxDbTransactionManager")
class ParsingTradeRepositorySupport(
private val parsingTradeRepository: ParsingTradeRepository,
) {
fun getParsingTrades(
registrationId: Long,
pageable: Pageable,
): Page<ParsingTrade?> {
val pageParsingTrade = parsingTradeRepository.findPage(pageable) {
select(
entity(ParsingTrade::class),
).from(
entity(ParsingTrade::class),
).whereAnd(
path(ParsingTrade::registrationId).eq(registrationId),
).orderBy(
Sorts.desc(Paths.path(ParsingTrade::listNo), nullOrder = Sort.NullOrder.LAST),
)
}
return pageParsingTrade
}
}
@ahnjunwoo-rsquare 안녕하세요.
Kotlin JDSL은 쿼리를 생성하는 라이브러리이기 때문에 Kotlin JDSL을 위한 별도의 추가작업은 필요 없습니다.