코프링으로 개발중에 ElementCollection으로 된 컬럼을 조건으로 조회하는 기능을 개발하던중 여러 여러가지 안되는 상황이 있어서 기록하고자 글을 남긴다...
해결방법은 kotlin-jdsl github 이슈에서 찾았다!!
exists subquery 문의 · Issue #774 · line/kotlin-jdsl
안녕하세요. exists subquery에 대해 문의드립니다. Entity 구조가 아래와 같을 때, @Entity class Notification( @Id val id: Long, @Enumerated(EnumType.STRING) @ElementCollection(fetch = FetchType.EAGER) @CollectionTable(name ...
github.com
엔티티 구조
일단 엔티티 내부에 enum list가 들어가야하는 상황이 있어서 어떻게 넣을까 생각하다가 ElementCollection을 사용하기로했다.
class Entity(
enumTypes: Set<EnumType>,
// 이하 생략
) {
....
@ElementCollection(targetClass = EnumType::class)
@CollectionTable(name = "enum_types", joinColumns = [JoinColumn(name = "entity_id")])
@Column(name = "enum_type", nullable = false)
@Enumerated(EnumType.STRING)
var _EnumTypes : MutableSet<EnumType> = enumTypes.toMutableSet()
protected set
....
}
이런식으로 enum 목록이 담긴 컬럼을 만들었다. 이렇게하면 테이블이 2개가 생기게 된다.
repository의 jdsl쿼리는 아래처럼 작성했다.
override fun findByEntity(query: FindQuery): Page<Entity> {
return queryFactory.pageQuery(query.getPageable()) {
selectFrom(Entity::class)
where(
and(
inFilter(query.enumType, Entity::enumTypes)
)
)
}
}
inline fun <reified T, R> SpringDataPageableQueryDsl<T>.inFilter(
value: R?,
property: KProperty1<T, R?>,
): PredicateSpec? {
return value?.let { col(property).`in`(it) }
}
inFilter라는 확장함수를 작성해서 만들어봤다.
발생한 에러
org.springframework.dao.InvalidDataAccessResourceUsageException: Multi valued paths are only allowed for the member of operator
대충 접근할수없는 경로라서 에러가 발생하게 된다.
분명이거는 다른사람도 발생했을것이라 생각하고 kotlin-jdsl의 이슈를 찾아보니 역시나 있었다!
변경된 코드
return queryFactory.pageQuery(query.getPageable()) {
select(entity(Entity::class))
from(entity(Entity::class))
join(Entity::enumTypes)
where(
and(
query.enumType?.let {
entity(EnumType::class).`in`(it)
}
)
)
}
join을 사용해서 해당 필드에 조인이 걸리게 작성하고 조건절에 Enum class를 넣어서 단수로 조건절을 적용했다.
저부분을 확장함수로 변경해서 사용하기 편하게 만드는건 나중에 따로 해봐야할것같다...