728x90
JPA에서 동적 쿼리를 어떻게 해결해야 하는가?
String jpql = "select o from Order o join o.member m" +
"where o.status = :status" +
" and m.name like :name";
em.createQuery(jpql,Order.class)//JPA에서 Join
.setParameter("status",orderSearch.getOrderStatus())
.setParameter("name",orderSearch.getMemberName())
//.setFirstResult(100)//페이징이 가능
.setMaxResults(1000) // 최대 1000건
.getResultList();
해당 로직을 동적 쿼리로 작성하기 위해서는 어떻게 해야 되나?
방법 1 : 문자열을 따로 빌드하여 작성한다.
String jpql = "select o From Order o join o.member m";
boolean isFirstCondition = true;
//주문 상태 검색
if (orderSearch.getOrderStatus() != null) {
if (isFirstCondition) {
jpql += " where";
isFirstCondition = false;
} else {
jpql += " and";
}
jpql += " o.status = :status";
}
//회원 이름 검색
if (StringUtils.hasText(orderSearch.getMemberName())) {
if (isFirstCondition) {
jpql += " where";
isFirstCondition = false;
} else {
jpql += " and";
}
jpql += " m.name like :name";
}
TypedQuery<Order> query = em.createQuery(jpql, Order.class)
.setMaxResults(1000);
if (orderSearch.getOrderStatus() != null) {
query = query.setParameter("status", orderSearch.getOrderStatus());
}
if (StringUtils.hasText(orderSearch.getMemberName())) {
query = query.setParameter("name", orderSearch.getMemberName());
}
return query.getResultList();
- 복잡하고 오류가 발생할 가능성이 너무 높다.
- 실무에서 사용하지 못한다.
방법 2 : Criteria 사용(JPA에서 표준으로 동적쿼리 문제를 해결하기 위해 제공하는 기술)
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Order> cq= cb.createQuery(Order.class);
Root<Order> o = cq.from(Order.class);
Join<Object,Object> m = o.join("member", JoinType.INNER);
List<Predicate> criteria = new ArrayList<>();
//주문 상태 검색
if(orderSearch.getOrderStatus() != null){
Predicate status = cb.equal(o.get("status"), orderSearch.getOrderStatus());
criteria.add(status);
}
//회원 이름 검색
if(StringUtils.hasText(orderSearch.getMemberName())){
Predicate name = cb.like(m.<String>get("name"),"%" + orderSearch.getMemberName() + "%");
criteria.add(name);
}
cq.where(criteria.toArray(new Predicate[criteria.size()]));
TypedQuery<Order> query = em.createQuery(cq).setMaxResults(1000);
return query.getResultList();
- 실무에서는 사용하지 못한다( 유지보수성이 좋지 않다)
- 어떤 쿼리를 동작시키고, 어떤 쿼리를 조인하는 것인지 파악하기 힘들다.
방법 3 : QueryDsl을 이용한다
QOrder order = QOrder.order;
QMember member = QMember.member;
return query
.select(order)
.from(order)
.join(order.member, member)
.where(statusEq(orderSearch.getOrderStatus()),
nameLike(orderSearch.getMemberName()))
.limit(1000)
.fetch();
- 가장 현실적인 방법 ( 실무에서 가장 많이 사용)
- 초기 설정하는 비용이 있긴 해도, 개발 생산성이 크게 증가
728x90
'실전! 스프링 부트와 JPA 활용1(웹 애플리케이션 개발)' 카테고리의 다른 글
| Ch07. 웹 계층 개발 - 회원 등록 (0) | 2021.12.07 |
|---|---|
| Ch07. 웹 계층 개발 - 홈 화면과 레이아웃 (0) | 2021.12.07 |
| Ch06. 상품 도메인 개발 - 주문 기능 테스트 (0) | 2021.12.06 |
| Ch06. 상품 도메인 개발 - 주문 Repository 개발, 주문 Service 개발 (0) | 2021.12.06 |
| Ch06. 주문 도메인 개발 - 주문, 주문상품 엔티티 개발 (0) | 2021.12.06 |