- 데이터베이스를 쉽게 다루기 위한 ‘데이터 액세스 기술’로 ORM(Object-Relational Mapping) 기법을 사용하여 자바 애플리케이션에서 사용하는 객체와 관계형 데이터베이스 사이의 매핑을 관리하는 ORM 기술에 대한 API 표준 명세서(인터페이스) 의미합니다. 이 API를 사용하여 개발자가 직접적인 SQL을 작성하지 않고도 데이터베이스에서 데이터를 저장, 업데이트, 삭제, 조회하는 등의 작업을 수행할 수 있게 해 줍니다.
- JPA는 표준화된 API를 제공함으로써, 다양한 ORM 프레임워크(예: Hibernate, EclipseLink, OpenJPA 등)와의 호환성을 보장합니다. 이로 인해 개발자는 특정 ORM 프레임워크에 종속되지 않고 필요에 따라 다른 프레임워크로 쉽게 전환할 수 있습니다.
https://adjh54.tistory.com/421
2) Criteria API
💡 Criteria API
- 자바의 JPA (Java Persistence API) 사양의 일부로서 기존 텍스트로 구성된 JPQL을 빌더 클래스를 사용하여 타입-세이프한 쿼리를 생성하는 API입니다.
- 기존 JPQL의 방식은 텍스트로 SQL를 작성하는 방식이기에 컴파일 타임에 오류를 검출할 수 없었으나, Criteria API에서는 타입-세이프 방식을 통해 컴파일 안정성을 제공하면서 컴파일 타임에 오류를 검출할 수 있습니다. - 또한, 런타임 시 동적 쿼리를 생성하는 데 유용합니다. 또한 동적 쿼리와 같은 복잡한 쿼리를 프로그래밍 방식으로 구성하여 객체 지향적인 방식으로 데이터베이스 쿼리를 작성할 수 있게 해 줍니다. - 단 해당 API는 복잡하고 장황한 코드를 만들 수 있어서 이해하고 유지보수하는 데 더 어려울 수 있습니다.
[ 더 알아보기] 💡 타입-세이프(type-safe)란?
- 프로그래밍 언어의 특성을 나타내는 용어로 프로그램이 실행되는 동안(런타임) 데이터의 타입을 체크하여 타입 오류를 방지하는 것을 의미합니다. - 타입-세이프한 프로그래밍 언어에서는 잘못된 타입의 데이터를 사용하려고 시도하면 컴파일 오류나 런타임 오류가 발생하여 버그를 방지합니다.
Criteria API의 시작점은 CriteriaBuilder를 사용하여 모든 쿼리 구성 요소를 생성하고, CriteriaQuery로 쿼리를 표현하는 객체를 구성하여 쿼리 수행 준비를 완료한다.
FROM 절 구성
Root
'엔티티'에 접근하여 쿼리를 시작하게 된다. 이는 SQL문의 FROM 절에 해당한다.
SELECT 절 구성
Selection
SQL 문의 컬럼 조회 부분을 구성한다. 이 부분에서는 엔티티 내의 필드를 조회하는 형태로 수행된다.
WHERE 절 구성
Predicates
쿼리의 결과를 제한하는 조건문을 구성하는 부분이다. 조건 술어의 접속에 따라 쿼리 결과의 제한이 지정된다.
ORDER 절 구성
Order
쿼리 결과를 정렬하는데 사용되는 정렬 표현식을 지정하는 부분이다.
쿼리 생성 및 결과값 반환
-
마지막으로, 위의 모든 구성 요소를 사용하여 최종 쿼리를 생성하고, 그 결과를 반환한다.
1. CriteriaBuilder & CriteriaQuery 구성 : Criteria Queries
💡 CriteriaBuilder & CriteriaQuery 구성
- CriteriaBuilder를 통해 Criteria API의 시작점으로 모든 쿼리 구성 요소를 생성하는 데 사용하며 인스턴스를 생성합니다. - CriteriaQuery를 통해 Criteria API로 작성된 쿼리를 표현하는 객체를 구성하여 쿼리를 수행할 준비를 완료합니다.
인터페이스
분류
설명
CriteriaQuery<T>
쿼리 인터페이스
Criteria API로 작성된 쿼리를 표현하는 인터페이스
CriteriaBuilder
쿼리 인터페이스
Criteria API의 시작점으로 모든 쿼리 구성 요소를 생성하는데 사용
@Repository
public class UserRepository {
@PersistenceContext
private EntityManager em;
public List<UserEntity> selectUserList(String userNm) {
// 1. CriteriaBuilder 인스턴스를 생성합니다.
CriteriaBuilder cb = em.getCriteriaBuilder();
// 2. UserEntity 타입의 CriteriaBuilder를 구성합니다.
CriteriaQuery<UserEntity> cq = cb.createQuery(UserEntity.class);
}
}
2. FROM 절 구성 : Query Roots
💡 FROM 절 구성 : Query Root - SQL문에서 FROM절에 해당하는 부분을 구성합니다. 해당 부분에서는 ‘엔티티’에 접근하여 시작되는 부분 수행이 됩니다.
3. UserEntity클래스를 기준으로 CriteriaQuery 내에 from 절을 구성합니다.
인터페이스
분류
설명
Root<X>
기타 인터페이스
쿼리의 Root를 표현하는 인터페이스
@Repository
public class UserRepository {
@PersistenceContext
private EntityManager em;
public List<UserEntity> selectUserList(String userNm) {
// 1. CriteriaBuilder 인스턴스를 생성합니다.
CriteriaBuilder cb = em.getCriteriaBuilder();
// 2. UserEntity 타입의 CriteriaBuilder를 구성합니다.
CriteriaQuery<UserEntity> cq = cb.createQuery(UserEntity.class);
// 3. 데이터를 조회하는 Query의 Root를 지정합니다.
Root<UserEntity> root = cq.from(UserEntity.class);
}
}
[ 더 알아보기 ] 💡 쿼리 루트(Query Root)
- SQL문에서 FROM절에 해당하는 부분에 사용이 되며 ‘엔티티’에 접근하여 쿼리가 시작이 됩니다. - 예를 들어, UserEntity 클래스를 기준으로 CriteriaQuery 내에 from 절을 구성하는 것이 쿼리 루트의 역할입니다.
3. SELECT 절 구성 : Selection
💡 SELECT 절 구성 : Selection - SQL문에서 컬럼을 조회하는 부분을 구성합니다. 해당 부분에서는 엔티티 내에서 필드를 조회하는 형태로 수행을 합니다.
4. select 메서드를 이용하여 root(엔티티) 전체를 조회하는 방식 : 전체 조회 5. multiselect 메서드를 이용하여 root(엔티티) 내에 필드를 조회하는 방식 : 일부 필드 조회
분류
메서드
리턴타입
설명
조회
select(Selection selection)
CriteriaQuery<T>
쿼리 결과에서 반환할 항목을 지정합니다.
조회
multiselect(List selectionList)
CriteriaQuery<T>
쿼리 결과에서 반환할 선택 항목을 지정합니다.
조회
multiselect(Selection... selections)
CriteriaQuery<T>
쿼리 결과에서 반환할 선택 항목을 지정합니다.
@Repository
public class UserRepository {
@PersistenceContext
private EntityManager em;
/**
* 사용자 리스트를 조회합니다.
*
* @param userNm
* @return
*/
public List<UserEntity> selectUserList(UserDto userDto) {
// 1. CriteriaBuilder 인스턴스를 생성합니다.
CriteriaBuilder cb = em.getCriteriaBuilder();
// 2. UserEntity 타입의 CriteriaBuilder를 구성합니다.
CriteriaQuery<UserEntity> cq = cb.createQuery(UserEntity.class);
// 3. 데이터를 조회하는 Query의 Root를 지정합니다.
Root<UserEntity> root = cq.from(UserEntity.class);
// 4. [전체 조회] CreateQuery 내에서 root라는 엔티티 전체 검색을 합니다.
cq = cq.select(root);
// OR
// 5. [일부 필드 조회] Root 내에서 특정 컬럼을 찾아서 일부만 조회합니다.
cq = cq.multiselect(
root.get("userId"),
root.get("userNm")
);
}
}
4. WHERE 절 구성 : Predicates
💡 WHERE 절 구성 : Predicates - SQL문에서 컬럼을 조회할 때 조건을 추가하는 부분을 구성합니다. 해당 부분에서는 CriteriaQuery로 조회할 엔티티와 엔티티 필드를 지정한 상태에서 이어서 조건문을 추가합니다.
5. 이전에 구성하였던 CriteriaQuery에 .where() 구문을 추가하여 구성��니다.
OR
6. Predicate 객체로 구성하며, CriteriaQuery 내에 .where() 구문으로 추가 구성합니다.
- Criteria API를 사용하면 코드가 복잡해질 수 있습니다. 복잡한 쿼리를 작성할 때, SQL 문을 직접 작성하는 것이 더 간단하고 이해하기 쉬울 수 있습니다. - JPQL과 비교하여 소스코드를 확인해 봤을 때도 상대적으로 복잡함을 확인할 수 있습니다.
💡 JPQL로 구성한 SQL문입니다.
💡 Criteria API로 구성한 SQL문입니다.
2. 복잡성
💡 복잡성
- Criteria API를 사용하면 쿼리를 작성하는 데 필요한 인터페이스와 메서드가 많아질 수 있고 이는 코드를 더 복잡하게 만들 수 있습니다.
💡 사용예시
- 동적 정렬을 하는 코드입니다. 해당 코드를 확인해 보더라도 처리를 위해 많은 코드가 들어가서 복��함을 확인할 수 있습니다.
3. 성능
💡 성능
- Criteria API는 실행 시점에 쿼리를 생성하고, 이로 인해 일부 상황에서 성능 저하가 발생할 수 있습니다. - 일반적은 MyBatis를 이용한 방법이나 Named Query를 이용하는 방법은 초기에 SQL문을 가져오기에 불러오는 시간이 상대적으로 짧습니다. - 그러나 Criteria API의 경우에는 메서드 호출 시 불러오기에 성능 저하가 발생할 수 있습니다.
4. 지원범위
💡 지원범위 - JPA 표준에서 제공하는 기능만 지원하므로, 특정 데이터베이스에 특화된 기능을 사용할 수 없습니다. - PostgreSQL, MySQL, Oracle 등 각각의 데이터베이스에서 지원하는 기능을 직접적으로 사용이 불가능합니다.