Peony의 기록 창고 🌼
반응형

JPA는 다양한 쿼리 방법을 지원한다.

  1. JPQL
  2. JPA Criteria
  3. QueryDSL
  4. 네이티브 SQL
  5. JDBC API 직접 사용, MyBatis, SpringJdbcTemplate 함께 사용

 

다양한 쿼리 방법 맛보기

우리가 배운 것 중에 가장 간단한 조회 방법은 EnfifyManager.find() 를 한 뒤, 객체 그래프를 탐색하는 방법이었다. (a.getB().getC())

이때, 만약 나이가 18살 이상인 회원을 모두 검색하고 싶다면? JPQL을 사용해보자.

 

JPA의 문제점

  • JPA를 사용하면 엔티티 객체를 중심으로 개발
  • 문제는 검색 쿼리
    : 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색해야 한다.
    • 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능하다.
      → 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요하다!

 

JPQL 특징

  • 객체 지향 쿼리 언어
  • SQL과 문법이 유사하다. (SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원)
  • JPQL : 엔티티 객체를 대상으로 쿼리 / SQL : 데이터베이스 테이블을 대상으로 쿼리

 

검색 예시

String jpql = "select m from Member m where m.id > 18";
List<Member> result = em.createQuery(jpql, Member.class).getResultList();
  • 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
  • 장점 : SQL을 추상화해서 특정 데이터베이스 SQL에 의존 X

 

Criteria 소개

JPQL : 결국은 단순한 String이다. -> 동적 쿼리를 만들기 어렵다.

대안 : Criteria

자바코드로 JPQL을 작성할 수 있도록 도와주는 방식이며 JPQL의 빌더 역할이라고 보면된다.

 

장점 : 자바 코드여서 오타가 나면 컴파일 오류가 난다. 동적 코드 가능

단점 : 유지보수가 너무 어렵다. (본인이 만들어도 나중에 다시 보면 이해하기 힘들다.)

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> query = cb.createQuery(Member.class);

Root<Member> m = query.from(Member.class);

CriteriaQuery<Member> cq = query.select(m);
String username = "da";
if (username != null) {
  cq = cq.where(cb.equal(m.get("name"), "kim"));
}

List<Member> result = em.createQuery(cq).getResultList();

사용하기에 너무 복잡하고 실용성이 없어 실무에서 사용하지 않으니 참고만 해보자. Criteria 대신에 QueryDSL 사용을 권장한다.

 

QueryDSL 소개

  • 문자가 아닌 자바 코드로 JPQL을 작성할 수 있다.
  • 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();

 

네이티브 SQL 소개

  • JPA가 제공하는 SQL을 직접 사용
  • JPQL로 해결할 수 없는 특정 데이터베이스에 의존적인 기능들
List<Member> resultList = em.createNativeQuery("select MEMBER_ID, city, street, zipcode, USERNAME, from MEMBER", Member.class).getResultList();

 

JDBC 직접 사용

JPA를 사용하면서 JDBC 커넥션을 직접 사용하거나, 스프링 JdbcTemplate, Mybatis 등 함께 사용 가능하다.

단, 영속성 컨텍스트를 적절한 시점에 강제로 플러시 필요하다. 즉, JPA에서 지원하는 기본 쿼리 문들은 모두 flush()처리를 해주지만, JDBC를 직접사용하는 경우 직접 flush()가 필요하다.

 

이 글은 김영한 님의 "자바 ORM 표준 JPA 프로그래밍 - 기본 편" 강의를 듣고 정리한 내용입니다.

반응형
profile

Peony의 기록 창고 🌼

@myeongju