QMember qMember = new QMember("m"); //직접 지정
QMember qMember = QMember.member; //기본 인스턴스 사용
위에 소스를 기본 인스턴스를 사용하면 간결하게 작성이 가능
import static jpabook.jpashow.doamin.QMember.member; //기본 인스턴스
public void basic() {
EntityManager em = emf.createEntityManager();
JPAQuery query = new JPAQuery(em);
List<Member> members =
query.from(member)
.where(member.name.eq("회원"))
.orderBy(member.name.desc())
.list(member); // fetch
}
and
, or
을 사용할 수 있다.and
연산을사용해도 됨.//QueryDSL 기본 쿼리 기능
JPAQuery query = new JPAQuery(em);
QItem item = QItem.item;
List<Item> list = query.from(item)
.where(item.name.eq("좋은상품").and(item.price.gt(20000)))
.list(item);
//실행된 JPQL
select item
from Item item
where item.name = ?1 and item.price >?2
//where 메서드에서 사용가능한 메서드
item.price.between(10000, 20000); //가격이 10000원 ~ 20000원 상품
item.name.contains("상품1"); //상품1이라는 이름을 포함한 상품 (like '%상품1%')
item.name.startWith("고급"); //이름이 고급으로 시작하는 상품 (like '고급%')
QItem item = QItem.item;
//기본 사용법
query.from(item)
.where(item.price.gt(20000))
.orderBy(item.price.desc(), item.stockQuantity.asc())
.offset(10).limit(20)
.list(item);
//restrict 사용
QueryModifiers queryModifiers = new QueryModifiers(20L, 10L); //limit, offset
List<Item> list = query.from(item)
.restrict(queryModifiers)
.list(item);
//실제 페이징 처리 -> 전체 데이터 수를 알아야 하므로 listResults()를 사용해야 한다.
SearchResults<Item> result =
query.from(item)
.where(item.price.gt(20000))
.offset(10).limit(20)
.listResults(item) //지금은 fetch()로 바뀜.
groupBy
를 사용하고, 그룹화된 결과에 제한을 걸려면 having
을 사용한다.
query.from(item)
.groupBy(item.price)
.having(item.price.gt(1000))
.list(item);
QOrder order = QOrder.order;
QMember member = QMember.member;
QOrderItem orderItem = QOrderItem.orderItem;
//기본 조인
query.from(order)
.join(order.member, member)
.leftJoin(order.orderItems, orderItem)
.list(order);
//조인 on 사용
query.from(order)
.leftJoin(order.orderItems, orderItem)
.on(orderItem.count.gt(2))
.list(order);
//페치 조인 사용 방법
query.from(order)
.innerJoin(order.member, member).fetch()
.leftJoin(order.orderItems, orderItem).fetch()
.list(order);
//세타 조인 방법 - from 절에 여러 조인을 사용하는 방식
query.from(order, member)
.where(order.member.eq(member))
.list(order);
unique()
list()
QItem item = QItem.item;
QItem itemSub = new QItem("itemSub");
//서브쿼리 - 한건
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)
.where(item.name.eq(itemSub.name))
.list(itemSub)
))
.list(item);
select 절에 조회 대상을 지정하는 것을 프로젝션이라고 한다.
QItem item = QItem.item;
List<String> result = query.from(item).list(item.name);
Tuple
타입을 사용한다.tuple.get()
을 통해 조회 대상을 지정하면 된다.QItem item = QItem.item;
List<Tuple> result = query.from(item).list(item.name, item.price);
for (Tuple tuple : result){
System.out.println("name = " + tuple.get(member.name));
System.out.println("age = " + tuple.get(member.age));
}
Projection
을 사용하면 된다.//ItemDTO 생성
public class ItemDTO {
private String username;
private int price;
public ItemDTO() {}
public ItemDTO(String username, int price) {
this.username = username;
this.price = price;
}
//Getter, Setter
...
}
프로퍼티 접근
Projections.bean()
메서드를 통해 값을 채운다.
QItem item = QItem.item;
List<ItemDTO> result = query.from(item).list(
Projections.bean(ItemDTO.class, item.name.as("username"), item.price));
필드 직접 접근
Projections.fields()
를 사용하면 필드에 직접 접근해서 값을 채워준다.QItem item = QItem.item;
List<ItemDTO> result = query.from(item).list(
Projections.fields(ItemDTO.class, item.name.as("username"), item.price));
생성자 사용
QItem item = QItem.item;
List<ItemDTO> result = query.from(item).list(
Projections.constructor(ItemDTO.class, item.name.as("username"), item.price));
QItem item = QItem.item;
JPAUpdateClause updateClause = new JPAUpdateClause(em, item);
long count = updateClause.where(item.name.eq("jpa 책"))
.set(item.price, item.price.add(100))
.execute();
QItem item = QItem.item;
JPADeleteClause deleteClause = new JPADeleteClause(em, item);
long count = deleteClause.where(item.name.eq("j
BooleanBuilder
를 사용하면 특정 조건에 따른 동적 쿼리를 편리하게 생성할 수 있다.SearchParam param = new SearchParam();
param.setName("시골개발자");
param.setPrice(10000);
QItem item = QItem.item;
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()));
}
List<Item> result = query.from(item)
.where(builder)
.list(item);
//검색 조건 정의
public class ItemExpression {
@QueryDelegate
public static BooleanExpression isExpensive(QItem item, Integer price) {
return item.price.gt(price);
}
}
//쿼리 타입에 생성된 결과
public class QItem extends EntityPathBase<Item> {
...
public BooleanExpression isExpensive(Integer price) {
return ItemExpression.isExpensive(this, price);
}
}