자바 플랫폼에서 영속성을 가진 엔터티 객체를 대상으로 하는 쿼리 언어이다.
SQL 쿼리와 유사하지만 테이블 대신 엔티티의 이름과 속성을 사용한다.
간결함 : SQL보다 간결하게 표현할 수 있다.
Named Queries : 이름으로 쿼리를 지정하여 재사용이 용이하다.
데이터베이스 종속성 : 특정 데이터베이스에 종속적인 기능을 사용하기 어려울 수 있다.
동적 쿼리 어려움 : 동적으로 쿼리를 생성하기가 어려울 수 있다.
"IT" 부서에 속한 모든 Employee 엔터티를 데이터베이스에서 검색하는 예제
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String department;
// Getters and setters
}
// JPQL 쿼리 사용 예시
String jpql = "SELECT e FROM Employee e WHERE e.department = :dept";
List<Employee> resultList = entityManager.createQuery(jpql, Employee.class)
.setParameter("dept", "IT")
.getResultList();
// SQL 쿼리 예시
SELECT * FROM Employee WHERE department = 'IT';
Hibernate 에서 제공하는 Criteria API 는 SQL 쿼리를 생성하기 위한 프로그래밍 방식의 인터페이스이다.
이 API 는 문자열 기반의 JPQL 이나 HQL 대신에 자바 코드를 사용하여 쿼리를 작성할 수 있게 해준다.
타입 안정성 : 컴파일 시점에 오류를 잡아낼 수 있도록 타입 안정성을 제공한다. 이는 오타나 잘못된 프로퍼티명으로 인한 런타임 오류를 방지할 수 있다.
동적 쿼리 생성 용이 : Criteria API 를 사용하면 동적으로 쿼리를 생성하기가 편리하다. 조건문을 사용하여 동적으로 조건을 추가하거나 변경할 수 있다.
가독성이 낮음 : 코드가 복잡해지고 가독성이 낮아질 수 있다. 특히 복잡한 쿼리의 경우에는 코드가 길어지고 이해하기 어려울 수 있다.
// 세션 팩토리에서 세션을 얻어온다.
Session session = sessionFactory.openSession();
// CriteriaBuilder를 얻어온다.
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
// CriteriaQuery를 생성하고 조회 대상 엔터티를 지정한다. 여기서는 Employee 엔터티를 조회한다.
CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
// Root는 엔터티에 대한 기본적인 위치를 나타낸다. 여기서는 Employee 엔터티를 기준으로 한다.
Root<Employee> root = criteriaQuery.from(Employee.class);
// CriteriaQuery의 select 메서드를 사용하여 어떤 엔터티나 속성을 선택할지 지정한다. 여기서는 모든 열을 선택한다.
criteriaQuery.select(root);
// CriteriaBuilder의 equal 메서드를 사용하여 부서가 "IT"인 조건을 추가한다.
criteriaQuery.where(criteriaBuilder.equal(root.get("department"), "IT"));
// 생성된 CriteriaQuery를 사용하여 세션에서 쿼리를 생성한다.
Query<Employee> query = session.createQuery(criteriaQuery);
// 쿼리를 실행하고 결과를 얻어온다.
List<Employee> resultList = query.getResultList();
// 세션을 닫는다.
session.close();
...
criteriaQuery.select(root);
// 동적으로 추가될 조건들을 담을 리스트를 생성한다.
List<Predicate> predicates = new ArrayList<>();
// someCondition이 true인 경우, 부서가 "IT"인 조건을 추가한다.
if (someCondition) {
predicates.add(criteriaBuilder.equal(root.get("department"), "IT"));
}
// anotherCondition이 true인 경우, 급여가 50000보다 큰 조건을 추가한다.
if (anotherCondition) {
predicates.add(criteriaBuilder.greaterThan(root.get("salary"), 50000));
}
// 동적으로 추가한 조건들을 WHERE 절에 적용한다.
criteriaQuery.where(predicates.toArray(new Predicate[0]));
// CriteriaQuery를 사용하여 세션에서 쿼리를 생성한다.
Query<Employee> query = session.createQuery(criteriaQuery);
...
단순한 쿼리 및 가독성 중요 시 : JPQL
동적 쿼리 생성 및 타입 안정성이 중요 시 : Criteria API
프로젝트 팀의 경험과 선호도에 따라 선택 가능
혼합 사용 : 복잡한 동적 쿼리를 Criteria API 로 작성하고, 단순한 정적 쿼리는 JPQL 을 사용하는 등의 접근 방식도 가능