본문 바로가기
Framework and Tool/JPA

JPA - 객체지향 쿼리 언어 - QueryDSL 배치쿼리, 동적쿼리

by ocwokocw 2021. 8. 24.

- 참조: 자바 ORM 표준 JPA 프로그래밍

- 수정, 삭제 배치쿼리

QueryDSL도 수정, 삭제 같은 배치쿼리를 지원한다. JPQL 배치쿼리와 같이 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리를 수행한다. JPQL 배치는 추후에 다루도록 한다.

 

QMember m = new QMember("m");

JPAUpdateClause updateClause = new JPAUpdateClause(em, m);

updateClause.where(m.name.startsWith("Name"))
	.set(m.age, m.age.add(1))
	.execute();

JPAQueryFactory query = new JPAQueryFactory(em);

List<Member> members = query.select(m)
	.from(m)
	.fetch();

members.forEach(member -> {
	System.out.println("User name: " + member.getName() + 
			", age: " + member.getAge());
});

 

수정은 JPAUpdateClause 라는걸 사용해서 수행한다. 실행된 SQL 을 보면 우리가 의도한대로 수행되는것을 알 수 있다.

 

Hibernate: 
    /* update
        Member m 
    set
        m.age = m.age + ?1 
    where
        m.name like ?2 escape '!' */ update
            member 
        set
            age=age+? 
        where
            name like ? escape '!'

 

삭제도 할 수 있는데 JPADeleteClause 를 사용한다.

 

QMember m = new QMember("m");

JPADeleteClause deleteClause = new JPADeleteClause(em, m);

deleteClause.where(m.name.eq("Name#1"))
	.execute();

JPAQueryFactory query = new JPAQueryFactory(em);

List<Member> members = query.select(m)
	.from(m)
	.fetch();

members.forEach(member -> {
	System.out.println("User name: " + member.getName() + 
			", age: " + member.getAge());
});

 

삭제도 실행하면 Delete 구문이 잘 실행되는것을 알 수 있다.

 

Hibernate: 
    /* delete 
    from
        Member m 
    where
        m.name = ?1 */ delete 
        from
            member 
        where
            name=?

- 동적 쿼리

BooleanBuilder 를 이용하면 특정 조건에 따른 동적 쿼리를 쉽게 생성할 수 있다.

 

SearchParam param = new SearchParam();
param.setAge(20);
param.setName("Name#4");

JPAQueryFactory query = new JPAQueryFactory(em);

QMember m = new QMember("m");

BooleanBuilder builder = new BooleanBuilder();
if(param.getAge() != null) {
	builder.and(m.age.gt(param.getAge()));
}

if(param.getName() != null &&
	!"".equals(param.getName())) {
	builder.and(m.name.eq(param.getName()));
}

List<Member> members = query.select(m)
	.from(m)
	.where(builder)
	.fetch();

members.forEach(member -> {
	System.out.println("Member name: " + member.getName() +
			", age: " + member.getAge());
});

 

SearchParam 은 검색조건을 나타내는 클래스를 임의로 생성한것이다. 각 검색조건이 null 이 아니고 문자열의 경우 비어있지 않다면 검색조건을 추가한다.

 

QueryDSL where 절에 BooleanBuilder 형인 builder 를 인자로 넘겼다. where 절은 Predicate 인터페이스형을 인자로 받는데 BooleanBuilder 도 Predicate 인터페이스를 구현하기 때문에 호환이 된다. (Java 8 의 Predicate 가 아니다.)

 

Hibernate: 
    /* select
        m 
    from
        Member m 
    where
        m.age > ?1 
        and m.name = ?2 */ select
            member0_.member_id as member_i1_6_,
            member0_.insert_datetime as insert_d2_6_,
            member0_.update_datetime as update_d3_6_,
            member0_.city as city4_6_,
            member0_.street as street5_6_,
            member0_.zipcode as zipcode6_6_,
            member0_.age as age7_6_,
            member0_.name as name8_6_ 
        from
            member member0_ 
        where
            member0_.age>? 
            and member0_.name=?
Member name: Name#4, age: 41

 

실행해보면 나이와 이름의 조건이 where 절에 모두 추가된것을 확인할 수 있다.

댓글