객체지향 쿼리 언어는 무엇이 있을까?
JPA에서 지원하는 쿼리
--
특정 데이터에 접근하기 위해서는 결국 SQL문을 통해 DB에 접근해야 한다.
JPA에는 다양한 쿼리 방법을 지원한다.
- JPQL
- JPA Criteria (Criteria API)
- QueryDSL
- Native Query
- JDBC API
JDBC를 직접 사용해도 된다.
다만 JDBC는 JPA와 관련이 없다 보니
바로 DB에 적용되는 것이 아니라서
영속성 컨텍스트를 적절한 시점에 강제로 flush()를 해줘야 한다.
--
JPQL (Java Persistence Query Language)
--
JPQL은
JPA에서 제공하는 객체 중신의 쿼리 언어로
기존 SQL문과 문법이 유사하지만, 테이블이 아닌 엔티티를 대상으로 동작한다.
(JPA가 JPQL을 SQL로 변환하여 실행하므로 DBMS에 독립적이다.)
JPA를 사용하면 엔티티 객체를 중심으로 개발을 진행해야 하는데
이때 엔티티 객체를 중심으로 개발하면 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색해야 한다.
다만 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능하다.
그래서 애플리케이션이 필요한 데이터만 DB에서 불러오려면
결국 검색 조건이 포함된 SQL이 필요하는데
해당 문제를 해결하기 위해 JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공한다.
JPQL 특징
- SQL문의 문법과 유사하며, SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN을 지원
- 엔티티 객체를 대상으로 작성하는 쿼리 (SQL은 DB 테이블을 대상으로 하는 쿼리)
예시 작성 방법
//검색 (Member 엔티티를 m으로 가정하고, Member의 name에 "kim"이 들어간 모든 데이터를 조회)
String jpql = "select m From Member m where m.name like ‘%kim%'";
List<Member> result = em.createQuery(jpql, Member.class).getResultList();
// 위에 작성한 JPQL을 실행하면 JPA가 아래 쿼리처럼 SQL로 변역 후 실행된다.
/*
select
m
from
Member m
where
m.name like '%kim%'
*/
select
m.MEMBER_ID as MEMBER_ID,
m.city as city,
m.street as street,
m.zipcode as zipcode,
m.NAME as NAME
from
Member m
where
m.NAME like '%kim%'
위 SQL문 처럼
작성한 JPQL은 주석처리가 되고
실제로는 작성한 JPQL 밑에 변역 된 SQL문으로 처리된다.
JPQL 문법과 SQL 문법의 차이 (= JPQL의 특징)
- DB 테이블이 아닌 엔티티 객체를 대상으로 하는 객체 지향 쿼리
- JPQL은 SQL처럼 특정 필드들을 작성하여 조회하는 것이 아닌 "m"으로 멤버 엔티티 자체를 통째로 조회
- SQL을 추상화하여 특정 DB SQL에 의존하지 않음
JPQL은 기본적으로 "지연 로딩"이 적용되어
필요할 때만 데이터를 가져온다.
--
Criteria API
--
기존 JPQL을 보면
단순한 String 형태로 SQL문을 작성하여
동적인 쿼리를 만들기 어렵다.
(문자열로 쿼리를 작성하여 동적으로 변경하기 어려움)
이를 보완하기 위해 사용되는 것이 Criteria다.
예시 코드
//Criteria 사용 준비
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> query = cb.createQuery(Member.class); //Member엔티티에 관련한 쿼리를 작성할 공간
//루트 클래스 (조회를 시작할 클래스) JPQL처럼 쿼리를 문자열이 아닌 코드로 짜고 있다.
Root<Member> m = query.from(Member.class);
//쿼리 생성
CriteriaQuery<Member> cq =
query.select(m).where(cb.equal(m.get("username"), “kim”));
List<Member> resultList = em.createQuery(cq).getResultList();
특징
- 문자가 아닌 자바코드로 JPQL 작성 가능
- JPQL 빌더 역할을 수행
- JPA 공식 기능
- 너무 복잡하고 실용성이 없음
Criteria는
너무 복잡하고 실용성이 없어서 사용하지 않고
대신 QueryDSL을 사용하는 것을 권장
--
QueryDSL
--
Criteria API보다
더욱 간결하고 직관적인 방식으로 동적 쿼리를 작성할 수 있는
"타입 세이프한 쿼리"다.
//JPQL
//select m from Member m where m.age > 18
JPAFactoryQuery query = new JPAQueryFactory(em);
QMember m = QMember.member;
List<Member> list = query.select(m)
.From(m)
.where(m.age.gt(18))
.orderBy(m.name.desc())
.fetch();
이 또한
기존 JPQL을 통해 작성했을 때 문자열로 작성하여 오타가 발생해도 오류로 잡아주는 것이 없었지만
QueryDSL은 코드로 작성하기 때문에 오타를 오류로 잡아준다.
특징
- 문자가 아닌 자바 코드로 JPQL을 작성
- JPQL의 빌더 역할
- 컴파일 시점에 문법 오류를 찾을 수 있음
- 동적 쿼리로 작성하기 편리
- 단순하고 쉽기 때문에 실무에서 사용 권장
--
네이티브 SQL
--
JPA가 제공하는 것으로
SQL을 직접 작성하여 사용할 수 있는 기능이다.
기존 JPQL로 해결할 수 없는 특정 DB에 의존적인 기능을 사용할 때 사용된다.
String sql = "SELECT * FROM member WHERE age > 20";
List<Member> result = em.createNativeQuery(sql, Member.class).getResultList();
- createNativeQuery() : SQL을 직접 실행
- Member.class : 결과를 엔티티로 매핑
--
참고 및 출처
'JPA' 카테고리의 다른 글
JPQL 기본 문법 (0) | 2025.04.07 |
---|---|
JPA의 데이터 타입 (0) | 2025.04.04 |
영속성 전이 (CASCADE) (+ 고아 객체) (0) | 2025.04.03 |
즉시 로딩 및 지연 로딩 (+ JPA의 프록시) (1) | 2025.04.02 |
상속관계 매핑 (+@MappedSuperclass) (1) | 2025.04.01 |
객체지향 쿼리 언어는 무엇이 있을까?
JPA에서 지원하는 쿼리
--
특정 데이터에 접근하기 위해서는 결국 SQL문을 통해 DB에 접근해야 한다.
JPA에는 다양한 쿼리 방법을 지원한다.
- JPQL
- JPA Criteria (Criteria API)
- QueryDSL
- Native Query
- JDBC API
JDBC를 직접 사용해도 된다.
다만 JDBC는 JPA와 관련이 없다 보니
바로 DB에 적용되는 것이 아니라서
영속성 컨텍스트를 적절한 시점에 강제로 flush()를 해줘야 한다.
--
JPQL (Java Persistence Query Language)
--
JPQL은
JPA에서 제공하는 객체 중신의 쿼리 언어로
기존 SQL문과 문법이 유사하지만, 테이블이 아닌 엔티티를 대상으로 동작한다.
(JPA가 JPQL을 SQL로 변환하여 실행하므로 DBMS에 독립적이다.)
JPA를 사용하면 엔티티 객체를 중심으로 개발을 진행해야 하는데
이때 엔티티 객체를 중심으로 개발하면 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색해야 한다.
다만 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능하다.
그래서 애플리케이션이 필요한 데이터만 DB에서 불러오려면
결국 검색 조건이 포함된 SQL이 필요하는데
해당 문제를 해결하기 위해 JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공한다.
JPQL 특징
- SQL문의 문법과 유사하며, SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN을 지원
- 엔티티 객체를 대상으로 작성하는 쿼리 (SQL은 DB 테이블을 대상으로 하는 쿼리)
예시 작성 방법
//검색 (Member 엔티티를 m으로 가정하고, Member의 name에 "kim"이 들어간 모든 데이터를 조회)
String jpql = "select m From Member m where m.name like ‘%kim%'";
List<Member> result = em.createQuery(jpql, Member.class).getResultList();
// 위에 작성한 JPQL을 실행하면 JPA가 아래 쿼리처럼 SQL로 변역 후 실행된다.
/*
select
m
from
Member m
where
m.name like '%kim%'
*/
select
m.MEMBER_ID as MEMBER_ID,
m.city as city,
m.street as street,
m.zipcode as zipcode,
m.NAME as NAME
from
Member m
where
m.NAME like '%kim%'
위 SQL문 처럼
작성한 JPQL은 주석처리가 되고
실제로는 작성한 JPQL 밑에 변역 된 SQL문으로 처리된다.
JPQL 문법과 SQL 문법의 차이 (= JPQL의 특징)
- DB 테이블이 아닌 엔티티 객체를 대상으로 하는 객체 지향 쿼리
- JPQL은 SQL처럼 특정 필드들을 작성하여 조회하는 것이 아닌 "m"으로 멤버 엔티티 자체를 통째로 조회
- SQL을 추상화하여 특정 DB SQL에 의존하지 않음
JPQL은 기본적으로 "지연 로딩"이 적용되어
필요할 때만 데이터를 가져온다.
--
Criteria API
--
기존 JPQL을 보면
단순한 String 형태로 SQL문을 작성하여
동적인 쿼리를 만들기 어렵다.
(문자열로 쿼리를 작성하여 동적으로 변경하기 어려움)
이를 보완하기 위해 사용되는 것이 Criteria다.
예시 코드
//Criteria 사용 준비
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> query = cb.createQuery(Member.class); //Member엔티티에 관련한 쿼리를 작성할 공간
//루트 클래스 (조회를 시작할 클래스) JPQL처럼 쿼리를 문자열이 아닌 코드로 짜고 있다.
Root<Member> m = query.from(Member.class);
//쿼리 생성
CriteriaQuery<Member> cq =
query.select(m).where(cb.equal(m.get("username"), “kim”));
List<Member> resultList = em.createQuery(cq).getResultList();
특징
- 문자가 아닌 자바코드로 JPQL 작성 가능
- JPQL 빌더 역할을 수행
- JPA 공식 기능
- 너무 복잡하고 실용성이 없음
Criteria는
너무 복잡하고 실용성이 없어서 사용하지 않고
대신 QueryDSL을 사용하는 것을 권장
--
QueryDSL
--
Criteria API보다
더욱 간결하고 직관적인 방식으로 동적 쿼리를 작성할 수 있는
"타입 세이프한 쿼리"다.
//JPQL
//select m from Member m where m.age > 18
JPAFactoryQuery query = new JPAQueryFactory(em);
QMember m = QMember.member;
List<Member> list = query.select(m)
.From(m)
.where(m.age.gt(18))
.orderBy(m.name.desc())
.fetch();
이 또한
기존 JPQL을 통해 작성했을 때 문자열로 작성하여 오타가 발생해도 오류로 잡아주는 것이 없었지만
QueryDSL은 코드로 작성하기 때문에 오타를 오류로 잡아준다.
특징
- 문자가 아닌 자바 코드로 JPQL을 작성
- JPQL의 빌더 역할
- 컴파일 시점에 문법 오류를 찾을 수 있음
- 동적 쿼리로 작성하기 편리
- 단순하고 쉽기 때문에 실무에서 사용 권장
--
네이티브 SQL
--
JPA가 제공하는 것으로
SQL을 직접 작성하여 사용할 수 있는 기능이다.
기존 JPQL로 해결할 수 없는 특정 DB에 의존적인 기능을 사용할 때 사용된다.
String sql = "SELECT * FROM member WHERE age > 20";
List<Member> result = em.createNativeQuery(sql, Member.class).getResultList();
- createNativeQuery() : SQL을 직접 실행
- Member.class : 결과를 엔티티로 매핑
--
참고 및 출처
'JPA' 카테고리의 다른 글
JPQL 기본 문법 (0) | 2025.04.07 |
---|---|
JPA의 데이터 타입 (0) | 2025.04.04 |
영속성 전이 (CASCADE) (+ 고아 객체) (0) | 2025.04.03 |
즉시 로딩 및 지연 로딩 (+ JPA의 프록시) (1) | 2025.04.02 |
상속관계 매핑 (+@MappedSuperclass) (1) | 2025.04.01 |