개발자꿈나무
객체지향 쿼리 언어 본문
★ JPA가 지원하는 다양한 쿼리 방법
- JPQL - 공식 지원 기능
- JPA Criteria - 공식 지원 기능
- QueryDSL - 비표준 오픈소스 프레임워크
- Native DSL - 공식 지원 기능
- JDBC API 직접 사용, Mybatis, SpringJdbcTemplate과 함께 사용
★ JPQL 소개
- 엔티티 객체를 조회하는 객체지향 쿼리
- 문법은 ansi 표준 SQL과 유사하게 지원
- SQL을 추상화해서 특정 데이터베이스에 의존하지 않음
//기본 JPQL
String jpql = "select m from Member as m where m.age >= 30"; //m.name은 컬럼명이 아니라 필드명
List<Member> resultList = em.createQuery(jpql, Member.class).getResultList(); //(실행할 JPQL, 반환할 엔티티 클래스 타입)
select
member0_.MEMBER_ID as member_i1_6_,
member0_.age as age2_6_,
member0_.city as city3_6_,
member0_.street as street4_6_,
member0_.zipcode as zipcode5_6_,
member0_.USERNAME as username6_6_,
member0_.endDate as enddate7_6_,
member0_.startDate as startdat8_6_
from
Member member0_
where
member0_.age>=30
★ Criteria 쿼리 소개
JPQL만을 사용하게 되면 제일 불편한 점이 동적쿼리를 작성하기 쉽지 않다는 점이다. 예시를 하나 들어보겠다.
String jpql = "select m from Member as m";
String str = "abcd";
if(str != null) {
String condition = " where m.age >= 30";
jpql += condition;
}
List<Member> resultList = em.createQuery(jpql, Member.class).getResultList();
이런 식으로 구성이 될텐데 jpql은 사실 단순히 String이므로 중간에 오타가 생기거나 condition 변수에 띄어쓰기만 하나 없더라도
select m from Member as mwhere m.age >= 30;
이렇게 작성이 될 것이다. 실제 애플리케이션을 제작하는 단계에서 이는 치명적인 버그가 될 수 있으므로 빌더를 사용해서 동적 쿼리를 작성하는 것이 안전할 것이다.
이를 도와주는 것이 Criteria 쿼리이다.
//Criteria 사용 - 빌더
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> query = cb.createQuery(Member.class);
//루트 클래스 (조회를 시작할 클래스)
Root<Member> m = query.from(Member.class);
//쿼리
CriteriaQuery<Member> cq =
query.select(m).where(cb.ge(m.get("age"),30));
List<Member> result = em.createQuery(cq).getResultList();
- 문자가 아닌 자바 코드로 JPQL을 작성할 수 있음
- JPQL 빌더 역할
- 동적 쿼리를 작성하기 편리
CriteriaQuery<Member> cq =
query.select(m);
String str = "abcd";
if(str != null) {
cq = cq.where(cb.ge(m.get("age"),30));
}
List<Member> result = em.createQuery(cq).getResultList();
- 단점 : 너무 복잡하고 코드도 한눈에 들어오지 않는다.
★ QueryDSL 소개
Criteria 쿼리 같은 경우 사용하기 복잡하고 SQL에서 사용하는 문법들과도 동떨어진 함수명들이 많아서 실용성이 조금 떨어진다.
그러나 QueryDSL은 훨씬 단순하고 SQL과 문법들이 유사하므로 유지보수도 더 쉽다.
QueryDSL은 JPA 공식 지원 기능은 아니고 오픈 소스 프레임워크이다.
JPAFactoryQuery query = new JPAQueryFactory(em); QMember m = QMember.member;
List<Member> list =
query.selectFrom(m)
.where(m.age.gt(30))
.orderBy(m.name.desc())
.fetch();
- 문자가 아닌 자바 코드로 JPQL을 작성할 수 있음
- JPQL 빌더 역할
- 컴파일 시점에 문법적 오류를 찾을 수 있음
- 동적쿼리 작성 편리함
- 단순하고 쉬움
★ Native SQL 소개
이름 그대로 JPQL이 아니라 SQL을 직접 사용할 수 있는 기능이다.
//네이티브 SQL 사용
List<Member> results = em.createNativeQuery("select MEMBER_ID, city, street, zipcode from member where age >= 30",
Member.class).getResultList(); //(실행할 JPQL, 반환할 엔티티 클래스 타입)
★ JDBC API 직접 사용, Mybatis, SpringJdbcTemplate과 함께 사용
- JDBC API를 직접 사용할 수 있으나 JPA를 우회해서 데이터베이스에 접근하므로 데이터 무결성을 훼손할 수 있음
- 사용하기 위해서는 꼭! 영속성 컨텍스트를 적절한 시점에 강제로 플러시해야함
- JPA를 우회해서 SQL을 실행하기 직전에 영속성 컨텍스트를 수동으로 플러시해서 데이터베이스와 영속성 컨텍스트를 동기화하면 됨
'자바 > JPA' 카테고리의 다른 글
JPQL - 프로젝션 (0) | 2023.08.31 |
---|---|
JPQL - 기본 문법과 기능 (0) | 2023.08.30 |
값 타입 컬렉션 (0) | 2023.08.28 |
값 타입과 불변 객체 (0) | 2023.08.23 |
갑 타입 - 임베디드 타입 (0) | 2023.08.23 |