그룹화 및 집계 기능
Criteria API에 간단한 요청을 하는 방법을 이미 알아냈습니다. 더 복잡한 쿼리를 만드는 방법을 살펴보겠습니다.
예를 들어 회사의 직원 수를 확인하는 쿼리를 작성하려고 합니다. HQL에서는 다음과 같이 표시됩니다.
select count(*) from Employee
그리고 Criteria API에서는 다음과 같습니다.
CriteriaQuery<Long> critQuery = builder.createQuery(Long.class);
critQuery.select(builder.count(critQuery.from(Employee.class)));
완전한 Java 코드는 다음과 같습니다.
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Long> critQuery = builder.createQuery(Long.class);
critQuery.select(builder.count(critQuery.from(Employee.class)));
Query<Long> query = session.createQuery(critQuery);
Long count = query.getSingleResult();
HQL을 사용해도 마찬가지입니다.
String hqlQuery = "select count(*) from Employee";
Query<Long> query = session.createQuery(hqlQuery);
Long count = query.getSingleResult();
이제 회사의 평균 급여를 계산해 봅시다. HQL 쿼리는 다음과 같습니다.
select avg(salary) from Employee
그리고 Criteria API에서는 다음과 같습니다.
CriteriaQuery<Double> critQuery = builder.createQuery(Double.class);
critQuery.select(builder.avg( critQuery.from(Employee.class).get("salary")));
완전한 Java 코드는 다음과 같습니다.
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Double> critQuery = builder.createQuery(Double.class);
critQuery.select(builder.avg( critQuery.from(Employee.class).get("salary")));
Query<Double> query = session.createQuery(critQuery);
Double avgSalary = query.getSingleResult();
기준 업데이트
테이블 수정은 테이블에서 데이터를 가져오는 것만큼 쉽습니다. 이를 위해 CriteriaBuilder에는 객체를 생성하는 createCriteriaUpdate() 라는 특수 메서드가 있습니다.기준 업데이트<T>데이터베이스의 엔터티를 업데이트하는 입니다.
10,000 미만을받는 직원의 급여를 인상합시다. 이 HQL 쿼리는 다음과 같습니다.
update Employee set salary = salary+20000 where salary<=10000
Criteria API에서는 다음과 같이 표시됩니다.
CriteriaUpdate<Employee> criteriaUpdate = builder.createCriteriaUpdate(Employee.class);
Root<Employee> root = criteriaUpdate.from(Employee.class);
criteriaUpdate.set("salary", "salary+20000");
criteriaUpdate.where(builder.lt(root.get("salary"), 10000));
Transaction transaction = session.beginTransaction();
session.createQuery(criteriaUpdate).executeUpdate();
transaction.commit();
기준삭제
레코드를 삭제하는 것이 변경하는 것보다 훨씬 쉽습니다. 이를 위해 객체를 생성하는 createCriteriaDelete() 특수 메서드가 있습니다.기준삭제<T>.
가치가 없는 모든 직원을 삭감합시다. 급여가 10,000 미만입니다. 이 HQL 쿼리는 다음과 같습니다.
delete from Employee where salary<=10000
Criteria API에서는 다음과 같이 표시됩니다.
CriteriaDelete<Employee> criteriaDelete = builder.createCriteriaDelete(Employee.class);
Root<Employee> root = criteriaDelete.from(Employee.class);
criteriaDelete.where(builder.lt(root.get("salary"), 10000));
Transaction transaction = session.beginTransaction();
session.createQuery(criteriaDelete).executeUpdate();
transaction.commit();
Criteria API의 이점
그렇다면 Criteria API의 이점은 무엇입니까? 쿼리는 번거롭습니다. HQL은 확실히 더 컴팩트할 것입니다.
첫째, 매개변수를 전달해야 하는 경우 HQL 쿼리는 그렇게 짧지 않습니다. 비교하다:
급여가 10,000 미만인 직원 수를 고려합니다. |
---|
HQL |
|
기준 API |
|
둘째, 쿼리를 동적으로 구성해야 하는 상황이 자주 발생합니다. 예를 들어 직원, 아파트 등을 필터링하는 웹 페이지가 있습니다. 일부 매개 변수가 사용자에게 중요하지 않은 경우 단순히 표시하지 않습니다. 따라서 대신 서버에 null이 전달됩니다.
귀하의 임무는 다음과 같습니다. 특정 직업(직업), 급여(급여) 및 고용 연도(YEAR(join_date))를 가진 직원을 선택하는 것입니다. 그러나 매개 변수 값이 null이면 필터에서 사용하지 마십시오.
그러면 HQL 쿼리는 다음과 같이 표시됩니다.
from Employee
where (occupation = :ocp)
and (salary = :sal)
and ( YEAR(join_date) = :jny)
그러나 "jny" 매개변수가 null인 경우 요청이 다음과 같기를 원하기 때문에 올바르게 작동하지 않습니다.
from Employee
where (occupation = :ocp)
and (salary = :sal)
null에 대한 매개 변수를 확인하여 요청을 다시 작성할 수 있습니다. 그러면 다음과 같은 결과가 나타납니다.
from Employee
where (occupation = :ocp or :ocp is null)
and (salary = :sal or :sal is null)
and ( YEAR(join_date)= :jny or :jny is null)
현실이 어떻게 더 복잡해지는지 보십니까? 현실은 종종 이렇습니다 :)
그러나 필터는 훨씬 더 복잡할 수 있습니다. "구매"라는 단어가 포함된 작업이 있는 사용자를 검색하는 것은 어떻습니까? 아니면 기한이 지난 사용자입니까?
from Employee
where (occupation = :ocp)
and (salary = :sal)
and (YEAR(join_date) = :jny)
and (tasks.name like '%buy%')
and (tasks.deadline < curdate())
그러한 쿼리 어딘가에 쓰거나 null이면 테이블 간의 조인이 취소되지 않습니다.
따라서 실제로 여러 테이블의 필드에 대해 복잡한 필터를 수행할 때 Criteria API가 도움이 될 수 있습니다. 그래서 간다.
자세한 내용은 공식 문서 에서 확인할 수 있습니다 .