Querydsl로 프로젝트를 하면서 많은 쿼리문을 작성하는데 필요 시 계속 구글링하면서 하기도 귀잖고 해서 일반적인 사용 방법에 대해 정리하려고 한다.
◆기본적인 사용
//객체 조회
val foos = query.selectFrom(foo).fetch()
//count 조회
val count = query.selectFrom(foo).fetchCount()
//join
val foos = query.selectFrom(foo)
.leftJoin(food).on(foo.id.eq(food.foo.id)
.fetch()
//ordering
val foos = query.selectFrom(foo)
.orderBy(foo.name.asc(), foo.age.desc()).fetch()
//update
query.update(foo).set(foo.name,"joy").where(foo.name.eq("jerrey")).execte()
◆Subqueries
Sub query를 사용하기 위해서는 JPAExpression을 사용해야 한다.
var foos = query
.selectFrom(foo)
.where(
foo.id.`in`(
JPAExpressions
.select(user.foo.id)
.from(user)
.where(user.age.isNotNull)
)
).fetch()
◆Paging 사용
Spring에서 제공하는 Paging 객체를 사용하면 order by 문구를 생성 시에 QClass로 생성되는 것을 볼 수 있다. 이 문제는 PathBuilder
와 OrderSpecifier
를 사용하여 쉽게 해결 할 수 있다.
pageable.sort.forEach {
val pathBuilder = PathBuilder(foo.type, foo.metadata)
query = query.orderBy(
OrderSpecifier(
if (it.isAscending) Order.ASC else Order.DESC,
pathBuilder.getString(it.property)
)
)
}
query = query.offset(pageable.offset).limit(pageable.pageSize.toLong())
var foos= query.fetch()
return PageImpl<foo>(foos, pageable, query.fetchCount())
마지막에 Page정보를 업데이트하여 return해야만 정확한 Page정보를 전달할 수 있다.
◆LAZY load 문제 해결
Data Entity에서 LAZY로 설정된 칼럼을 방문함에 있어 LazyInitializationException 이 발생할 수 있다. 참고링크, 이를 해결하기 위해 방법은 여러가지가 있지만 QueyDSL를 이용하여 쉽게 해결하는 방법을 소개 하려고 한다. left join후 강제로 join를 fetch 시키는 방법이다.
var query = query
.selectFrom(user)
.leftJoin(user.foo)
.where(user.foo.id.eq(ids))
return query.fetchJoin().fetch()
마지막 실행문에서 fetchJoin를 먼저 해줘야만 LAZY로 설정된 객체를 같이 가져온다.
◆ 2 Depth fetch
종종 업무를 하다보면 2depth object까지 조회해야하는 경우가 있고 그 과정에서 LAZY 에러가 발생하는 경우가 있다. 이경우 아래와 같이 사용하면 된다.
query
.select(foo)
.from(foo)
.innerJoin(foo.user, user).fetchJoin()
.innerJoin(user.role, rol).fetchJoin()
.where(
foo.user.id.eq(id),
).fetch()
Join과 동시에 fetchJoin을 실행하여 구현 가능 하다.
◆ BooleanExpression 사용
조건문이 많은 경우 query를 더 직관적으로 사용할 수 있는 방법이다
fun eqEmail(userEmail: String?): BooleanExpression? {
userEmail ?: return null
return user.email.like("$userEmail%")
}
fun predicateUserType(type: String): BooleanExpression? {
if (type == "admin") {
return user.role.name.qe("admin");
}
return user.role.name.notEqualsIgnoreCase("admin")
}
fun test(){
var query = query
.selectFrom(user)
.leftJoin(user.foo)
.where(eqEmail("abc@abc.com"),
predicateUserType("admin"))
return query.fetchJoin().fetch()
}
https://vimsky.com/examples/detail/java-class-com.querydsl.jpa.JPAExpressions.html
http://querydsl.com/static/querydsl/latest/reference/html/ch03s02.html
https://ict-nroo.tistory.com/117
https://jsonobject.tistory.com/605
'Spring boot' 카테고리의 다른 글
AWS SES 사용하기 (0) | 2022.03.01 |
---|---|
[Spring] 코드에서 Active Profile 가져오기 (0) | 2022.01.09 |
[Spring] Cache (0) | 2022.01.03 |
[Spring] Maven Wrapper (0) | 2022.01.03 |
[Spring]JobRunr libary 사용 (0) | 2021.12.19 |
Comment