객체지향 쿼리 소개

Daniel6364·2022년 10월 18일
0

JPQL

JPA는 복잡한 검색 조건을 사용해서 엔티티 객체를 조회할 수 있는 다양한 쿼리 기술을 지원한다.

  • 테이블이 아닌 객체를 대상으로 검색하는 객체지향 쿼리
  • SQL을 추상화해서 특정 데이터베이스 SQL에 의존하지 않는다.

SQL이 데이터베이스 테이블을 대상으로 하는 데이터 중심의 쿼리라면 JPQL은 엔티티 객체를 대상으로 하는 객체지향 쿼리이다.

JPQL을 사용하면 JPA는 이 JPQL을 분석한 다음 적절한 SQL을 만들어 데이터베이스를 조회한다.

그리고 조회한 결과로 엔티티 객체를 생성해서 반환한다.

  • JPQL : Java Persistence Query Language
  • Criteria : Criteria Query (JPQL을 편하게 작성하도록 도와주는 API, 빌더클래스 모음
  • 네이티브 SQL : Native SQL (JPA에서 JPQL 대신 직접 SQL을 사용할 수 있다.)
  • QueryDSL : Criteria 쿼리처럼 JPQL을 편하게 작성하도록 도와주는 빌더 클래스 모음, 비표준 오픈소스 프레임워크다.
  • JDBC 직접 사용 : MyBatis 같은 SQL 매퍼 프레임워크 (필요하면 JDBC를 직접 사용할 수 있다.)

가장 중요한건 JPQL이다. Criteria나 QueryDSL은 JPQL을 편하게 작성하도록 도와주는 빌더 클래스일 뿐이다. 따라서 JPQL을 이해해야 나머지도 이해할 수 있다.

// JPQL 사용
String jpql = "select m from Member as m where m.username = 'kim'";
List<Memver> resultList = em.createQuery(jpql, Member.class).getResultList();

Criteria 쿼리

CriteriaJPQL을 생성하는 빌더 클래스다.

Criteria의 장점은 문자가 아닌 query.select(m).where(...)처럼 프로그래밍 코드로 JPQL을 작성할 수 있다는 점이다.

Criteria 쿼리를 사용하게되면 문자기반 쿼리의 단점을 보완할 수 있다.

예를 들면 JPQL에서 select m from Membbbbeer m처럼 오타가 있다고 가정하면, 컴파일은 성공하고 애플리케이션을 서버에 배포할 수 있다. 문제는 해당 쿼리가 실행되는 런타임 시점에 오류가 발생한다는 점이다.

Criteria의 장점

  • 컴파일 시점에 오류를 발견할 수 있다.
  • IDE를 사용하면 코드 자동완성을 지원한다.
  • 동적 쿼리를 작성하기 편하다.

(JPA는 2.0부터 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.equal(m.get("username"), "kim"));
List<Member> resultList = em.createQeury(cq).getResultList();

아쉬운 점은 m.get("username")에서 필드 명을 문자로 작성했다. 메타 모델을 사용하면 온전히 코드만 사용해서 쿼리를 작성할 수 있다.

// 메타 모델 사용 전 -> 사용 후
m.get("username") -> m.get(Member_.username)

결론
Criteria가 가진 장점이 많지만 모든 장점을 상쇄할 정도로 복잡하고 장황하다. 따라서 사용하기 불편한 건 물론이고 Criteria로 작성한 코드도 한눈에 들어오지 않는다는 단점이 있다.


QueryDSL

QueryDSLCriteria처럼 JPQL빌더 역할을 한다.

QueryDSL의 장점은 코드 기반이면서 단순하고 사용하기 쉽다. 그리고 작성한 코드도 JPQL과 비슷해서 한눈에 들어온다. QueryDSLCriteria를 비교하면 Criteria너무 복잡하다.

// 준비
JPAQuery query = new JPAQuery(em);
QMember member = QMember.member;

// 쿼리, 결과조회
List<Member> members = 
	query.from(member)
    .where(member.username.eq("kim"))
    .list(member);

QueryDSL도 어노테이션 프로세서를 사용해서 쿼리 전용 클래스를 만들어야 한다. QMember는 Member 엔티티 클래스를 기반으로 생성한 QueryDSL 쿼리 전용 클래스다.


네이티브 SQL

JPASQL을 직접 사용할 수 있는 기능을 지원 = 네이티브 SQL

네이티브 SQL을 사용하는 이유

  1. 특정 데이터베이스에 의존하는 기능을 사용해야 할때
    (ex. 오라클 DB에서만 사용되는 CONNECT BY 기능이나 특정 DB에서만 동작하는 SQL힌트 사용시)
  2. SQL은 지원하지만 JPQL이 지원하지 않는 기능도 있을 때
  3. 단점은 특정 데이터베이스에 의존하는 SQL을 작성해야 한다. 따라서 데이터베이스를 변경하면 네이티브 SQL도 수정해야 한다.
String sql = 
	"SELECT ID, AGE, TEAM_ID, NAME FROM MEMBER WHERE NAME = 'kim'";

List<Member> resultList = 
	em.createVativeQuery(sql, Member.class).getResultList();

profile
The Office Lover

0개의 댓글