Querydsl - 중급 문법(2)

YulHee Kim·2022년 1월 12일
0

Querydsl

목록 보기
6/6

김영한님의 '실전! Querydsl'을 수강하며 정리하는 글입니다

중급 문법

✔️ 동적 쿼리 - BooleanBuilder 사용

동적 쿼리를 해결하는 두가지 방식

  • BooleanBuilder
  • Where 다중 파라미터 사용
    @Test
    public void dynamicQuery_BooleanBuilder() {
        String usernameParam = "member1";
        Integer ageParam = 10;

        List<Member> result = searchMember1(usernameParam, ageParam);
        assertThat(result.size()).isEqualTo(1);
    }

    private List<Member> searchMember1(String usernameCond, Integer ageCond) {

        BooleanBuilder builder = new BooleanBuilder();
        if (usernameCond != null) {
            builder.and(member.username.eq(usernameCond));
        }

        if (ageCond != null) {
            builder.and(member.age.eq(ageCond));
        }
        return queryFactory
                .selectFrom(member)
                .where(builder)
                .fetch();
    }

✔️ 동적 쿼리 - Where 다중 파라미터 사용

    @Test
    public void dynamicQuery_WhereParam() {
        String usernameParam = "member1";
        Integer ageParam = 10;

        List<Member> result = searchMember2(usernameParam, ageParam);
        assertThat(result.size()).isEqualTo(1);
    }

    private List<Member> searchMember2(String usernameCond, Integer ageCond) {
        return queryFactory
                .selectFrom(member)
                //.where(usernameEq(usernameCond), ageEq(ageCond))
                .where(allEq(usernameCond, ageCond))
                .fetch();
    }

    private BooleanExpression usernameEq(String usernameCond) {
        return usernameCond != null ? member.username.eq(usernameCond) : null;
    }

    private BooleanExpression ageEq(Integer ageCond) {
        return ageCond != null ? member.age.eq(ageCond) : null;
    }
  • where 조건에 null 값은 무시된다.
  • 메서드를 다른 쿼리에서도 재활용 할 수 있다
  • BooleanBuilder 보다 쿼리 자체의 가독성이 높아진다.

조합 가능

    private BooleanExpression allEq(String usernameCond, Integer ageCond) {
        return usernameEq(usernameCond).and(ageEq(ageCond));
    }

✔️ 수정, 삭제 벌크 연산

쿼리 한번으로 대량 데이터 수정

    @Test
    public void bulkUpdate() {

        long count = queryFactory
                .update(member)
                .set(member.username, "비회원")
                .where(member.age.lt(28))
                .execute();

        em.flush();
        em.clear();

        List<Member> result = queryFactory
                .selectFrom(member)
                .fetch();

        for (Member member1 : result) {
            System.out.println("member1 = " + member1);
        }
    }

JPQL 배치와 마찬가지로, 영속성 컨텍스트에 있는 엔티티를 무시하고 바로 DB에 접근하기 때문에 영속성 컨텍스트와, 디비에 있는 데이터가 다르다는 문제가 발생한다. 그러므로 배치 쿼리를 실행하고 나면 영속성 컨텍스트를 초기화 하는 것이 안전하다.

기존 숫자에 더하기, 곱하기

    @Test
    public void bulkAdd() {
        long count = queryFactory
                .update(member)
                //.set(member.age, member.age.add(1))
                .set(member.age, member.age.multiply(2))
                .execute();
    }

쿼리 한번으로 대량 데이터 삭제

 long count = queryFactory
            .delete(member)
            .where(member.age.gt(18))
            .execute();

✔️ SQL function 호출하기

SQL function은 JPA와 같이 Dialect에 등록된 내용만 호출할 수 있다.

member -> M으로 변경하는 replace 함수 사용

@Test
    public void sqlFunction() {
        List<String> result = queryFactory
                .select(Expressions.stringTemplate("function('replace', {0}, {1}, {2})",
                        member.username, "member", "M"))
                .from(member)
                .fetch();

        for (String s : result) {
            System.out.println("s = " + s);
        }
    }

소문자로 변경해서 비교

@Test
    public void sqlFunction2() {
        List<String> result = queryFactory
                .select(member.username)
                .from(member)
//                .where(member.username.eq(
//                        Expressions.stringTemplate("function('lower', {0})", member.username)))
                .where(member.username.eq(member.username.lower()))
                .fetch();

        for (String s : result) {
            System.out.println("s = " + s);
        }
    }

lower같은 자주쓰이는 함수들은 querydsl이 대부분 내장하고 있다. 따라서 주석처리와 밑에 .where(member.username.eq(member.username.lower()))는 똑같은 코드이다.

profile
백엔드 개발자

0개의 댓글