[JPA] QueryDSL

시나브로·2021년 7월 22일
0

JPA

목록 보기
12/12
post-thumbnail

1. QueryDSL


QueryDSL을 사용하면 문법 오류를 컴파일 단계에서 잡을 수 있고 문자 기반의 JPQL보다 동적 쿼리를 안전하게 생성할 수 있는 장점이 있다.


1.1 조회


ex)

JPAQuery query = new JPAQuery(em);
QItem item = QItem.item;
List<Item> list = query.from(item)
	.where(item.name.eq("테스트").and(item.price.gt(2000)))
    .list(item);

결과 조회

보통 uniqueResult()list()를 사용한다.

  • uniqueResult() : 조회 결과가 한 건일 때 사용한다. 결과가 없을 시 null 반환, 한 건 이상일 시, NonUniqueResultException 예외가 발생한다
  • singleResult() : 하나 이상이면 처음 데이터를 반환한다.
  • list() : 결과가 여러개일 때 사용한다. 결과가 없으면 빈 컬렉션을 반환한다.

1.2 페이징


QItem item = QItem.item;

query.from(item)
	.offset(10).limit(20)
    .listResults(item);

offsetlimit을 사용하여 페이징 처리를 한다.

  • listResults : 전체 데이터 조회를 위한 count 쿼리를 한번 더 실행한다. result.getTotal()을 통해 전체 데이터 수를 얻어올 수 있다.



1.3 조인


innerJoin, leftJoin, rightJoin, fullJoin, fetchJoin이 사용 가능하다.


기본 Join

query.from(order)
	.join(order.member, member)
    .leftJoin(order.orderItems, orderItems)
    .list(order);

on 사용

query.from(order)
    .leftJoin(order.orderItems, orderItems)
    .on(orderItem.count.gt(2))
    .list(order);

fetch join 사용

query.from(order)
    .innerJoin(order.orderItems, orderItems).fetch()
    .list(order);



1.4 서브쿼리


서브쿼리의 결과가 하나면 unique(), 여러 건이면 list()를 사용할 수 있다.


단일 서브 쿼리

query.from(item)
	.where(item.price.eq(
    	new JPASubQuery().from(itemSub).unique(itemSub.price.max())))
        .list(item);

다중 서브 쿼리

query.from(item)
	.where(item.in(
    	new JPASubQuery().from(itemSub).list(itemSub)))
        .list(item);



1.5 프로젝션


select절에서 조회 대상을 지정하는 것을 프로젝션이라 한다.


List<Tuple> result = query.from(item).list(item.name, item.price);
result.get(item.name);
result.get(item.price);

빈 생성

List<Tuple> result = query.from(item)
	.list(Projections.bean(ItemDto.class, item.name.as("username"), item.price));

List<Tuple> result = query.from(item)
	.list(Projections.fields(ItemDto.class, item.name.as("username"));

List<Tuple> result = query.from(item)
	.list(Projections.constructor(ItemDto.class, item.name);



1.6 수정, 삭제 배치 쿼리


영속성 컨텍스트를 무시하고 db에 직접 쿼리한다.


update

JPAUpdateClause updateClause = new JPAUpdateClause(em, item);
long count = updateClause.where(item.name.eq("JPA"))
	.set(item.price, item.price.add(100))
    .execute();

delete

JPADeleteClause deleteClause = new JPADeleteClause(em, item);
long count = deleteClause.where(item.name.eq("JPA"))
    .execute();



1.7 동적 쿼리


BooleanBuilder builder = new BooleanBuilder();
if(StringUtils.hasText(param.getName())) {
	builder.and(item.name.contains(param.getName()));
}
if (param.getPrice() != null) {
	builder.and(item.price.gt(param.getPrice()));
}
query.from(item)
	.where(builder
    .list(item);






참고 도서

  • 자바 ORM 표준 JPA 프로그래밍 - 김영한
profile
Be More!

0개의 댓글