정적 쿼리
parameter가 반드시 넘어오는 경우
public List<Order> findAll(OrderSearch orderSearch){
return em.createQuery("select o from Order o join o.member m"+" where o.status = :status "+" and m.name like :name", Order.class)
.setParameter("status",orderSearch.getOrderStatus())
.setParameter("name", orderSearch.getMemberName())
.setFirstResult(100)
.setMaxResults(1000)
.getResultList();
}
parameter가 없는 경우
public List<Order> findAll(OrderSearch orderSearch){
return em.createQuery("select o from Order o join o.member m", Order.class)
.setFirstResult(100)
.setMaxResults(1000)
.getResultList();
}
동적쿼리
- 특정 조건들이나 상황에 따라 변경됨.
ex) 검색 기능
- parameter 값이 없으면 전체 데이터 검색,
- parameter 값이 있으면 그 값으로 데이터 검색.
1. JPQL 사용
public List<Order> findAll(OrderSearch orderSearch){
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();
}
단점
- jpql을 문자열로 만든 후, string을 추가하는 방식 --> jpql에 띄어쓰기 하나라도 틀리면 오류발생.
2. JPA Criteria
public List<Order> findAllByCriteria(OrderSearch orderSearch){
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(cb.and(criteria.toArray(new Predicate[criteria.size()])));
TypedQuery<Order> query = em.createQuery(cq).setMaxResults(1000);
return query.getResultList();
}
단점
- 유지보수 제로에 가까움. 무슨 쿼리가 생성될 지 예측 하기어려움.
- Criteria는 Spring의 표준 스펙, but 실무에서 사용하지 않음.
3. Querydsl
public List<Order> findAll(OrderSearch orderSearch){
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();
}
private BooleanExperssion statusEq(OrderStatus statusCond){
if(statusCond == null){
return null;
}
return order.status.eq(statusCond);
}
private BooleanExperssion nameLike(String nameCond) {
if(!StringUtils.hasText(nameCond)){
return null;
}
return member.name.like(nameCond);