JPA

JPA 쿼리 언어 종류

쭈녁 2022. 12. 22. 21:49

JPA 지원하는 쿼리 방식

  • JPQL
  • JPA Criteria
  • QueryDSL
  • 네이티브 SQL
  • JDBC API 직접 사용, MyBatis, SpringJdbcTEmplete 함께 사용

JPQL

  • 조회 방법이 가장 단순함(EntityManager.find())
  • 객체 그래프 탐색이 가능함(a.getB().getC)

조건을 주고 검색 할 때

  • JPA를 사용하면 엔티티 객체 중심으로 개발
  • 검색할 때도 테이블이 아닌 엔티티를 대상으로 검색하는 것이 객체 지향적임
  • 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능
  • 애플리케이션이 필요한 데이터만 DB에서 불러오는 검색조건이 포함된 쿼리문이 필요

JPQL 특징

  • JPQL = JPA에서 SQL을 추상화한 객체지향 쿼리 언어 제공
  • SQL문과 유사한 SELECT, FROM,WHERE,GROUP BY, HAVING, JOIN 지원
  • JPQL은 엔티티 객체를 대상으로 쿼리
  • SQL은 데이터 베이스 테이블을 대상으로 쿼리
  • 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
  • SQL을 추상화 해서 특정 데이터 베이스 SQL에 의존하지 않는다
  • JPQL은 SQL로 변환된다.
List<Member> resultList = em.createQuery("SELECT m FROM Member AS m WHERE m.name LIKE '%김%'", Member.class)
.getResultList();


Criteria

  • JPQL의 경우 동적 쿼리에서 동적인 부분의 쿼리를 직접 작성해야하는 단점이 있다. 이를 보완하는게 Criteria
  • JPQL과 같이 String으로 직접 쿼리를 넣어주는 것이 아닌 메서드를 통한 쿼리 작성임으로 오타를 컴파일 오류로 잡을 수 있다.
  • JPQL 빌더 역할
  • 단점 : 복잡하고 실용성이 떨어진다.(SQL문 같지 않고 가독성이 떨어짐)
  • 대신 QueryDSL 사용 권장
//Criteria
//사용 준비
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> query = cb.createQuery(Member.class);
//SELECT,FROM 지정
Root<Member> m = query.from(Member.class);

CriteriaQuery<Member> cq = query.select(m);
String name = "111";

//조건부 where 동적 쿼리 작성 시 용이
if (name != null) {
    cq = cq.where(cb.equal(m.get("name"), "kim"));
}

 


QueryDSL

  • 문자가 아닌 자바코드로 JPQL작성 가능
  • JPQL 빌더 역할
  • 컴파일 시점에 문법 오류를 찾을 수 있음
  • 동적 쿼리 작성이 편리함
  • 실무 사용 권장
JPAFactoryQuery query = new JPAQueryFactory(em);
 QMember m = QMember.member;
 List<Member> list =
 query.selectFrom(m)
 .where(m.age.gt(18))
 .orderBy(m.name.desc())
 .fetch();

설정 및 Qfile 생성 등 사전 작업이 필요하긴 하나 동적 쿼리를 작성하기 매우 용이하고 SQL문과 매우 흡사해 가독성도 매우 높다. QueryDSL는다른 포스팅 글을 통해 정리 해볼 예정이다.

 


네이티브 SQL

  • JPA가 제공하는 SQL 을 직접 사용하는 기능
  • JPQL로 해결할 수 없는 특정 테이터 베이스에 의존적인기능

ex) 오라클 CONNECT BY, 특정 DB만 사용하는 SQL 힌트

List resultList2 = em.createNativeQuery("select MEMBER_ID, city, street, zipcode, NAME form MEMBER", Member.class)
.getResultList();

해당 내용은 사용해 본 적이 없어 앞으로 접해보게 되면 깊게 학습하여 포스팅 할듯 싶다.

 

JDBC 직접 사용

JdbcTemplete 사용시 주의 사항

JPA의 경우 쿼리를 직접 생성해서 넣을때 Flush를 호출해 영속성 컨텍스트에 포함시키는 기능이 있다. (em.createQuery 등등)

하지만 JdbcTemplete의 경우 이러한 기능이 포함되어 있지 않기 때문에 JdbcTemplete을 함께 사용할때는 쿼리문 전에 영속성 컨텍스트에 올리는 작업 (강제 fulsh)가 필요하다.





'JPA' 카테고리의 다른 글

JPQL문법 2 (페치 조인,벌크 연산)  (0) 2022.12.23
JPQL 문법 1  (1) 2022.12.22
값 타입 정리  (0) 2022.12.21
프록시와 연관관계 (즉시로딩/지연로딩)  (0) 2022.12.21
@MappedSuperclass  (0) 2022.12.20