Querydsl 일반적인 사용 정리

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로 생성되는 것을 볼 수 있다. 이 문제는 PathBuilderOrderSpecifier를 사용하여 쉽게 해결 할 수 있다.

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://ksabs.tistory.com/186

https://jsonobject.tistory.com/605

https://hojak99.tistory.com/578

https://velog.io/@sonaky47/querydsl-%EB%91%90%EB%B2%88%EC%A7%B8-%EA%B9%8A%EC%9D%B4%EB%A5%BC-fetch-%ED%95%B4%EB%B3%B4%EC%9E%90

'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