개발자꿈나무

객체지향 쿼리 언어 본문

자바/JPA

객체지향 쿼리 언어

망재이 2023. 8. 29. 14:27

★ 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을 실행하기 직전에 영속성 컨텍스트를 수동으로 플러시해서 데이터베이스와 영속성 컨텍스트를 동기화하면 됨

728x90

'자바 > JPA' 카테고리의 다른 글

JPQL - 프로젝션  (0) 2023.08.31
JPQL - 기본 문법과 기능  (0) 2023.08.30
값 타입 컬렉션  (0) 2023.08.28
값 타입과 불변 객체  (0) 2023.08.23
갑 타입 - 임베디드 타입  (0) 2023.08.23