객체지향 쿼리 언어 소개

Mina Park·2022년 10월 22일
0

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

  • 📌JPQL
  • JPA Criteria
  • 📌QueryDSL
  • native SQL
  • JDBC API를 직접 사용, MyBatis, SpringJdbcTemplate 함께 사용
    • 실무에서는 95% JPQL + QueryDSL 사용

1. JPQL 소개

  • 📌가장 기본이므로 반드시 사용 숙지
  • JPA를 사용하면 엔티티 객체를 중심으로 개발하는 것
  • 문제는 검색 쿼리
    • 검색시에도 테이블이 아닌 엔티티 객체를 대상으로 검색
    • 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능
    • 애플리케이션이 필요로 하는 데이터만 DB에서 조회하려면 결국 검색 조건이 포함된
      SQL이 필요
  • SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공
    • SQL과 유사한 문법 제공(안시 표준)
      - SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원
      • JPQL: 엔티티 객체를 대상으로 쿼리
        - 객체 지향 쿼리, 특정 데이터베이스에 의존 X
      • SQL: 데이터베이스 테이블을 대상으로 쿼리
 List<MemberMapping> result = em.createQuery("select m from MemberMapping m where m.username like '%kim%'", MemberMapping.class).getResultList();
Hibernate: 
    /* select
        m 
    from
        MemberMapping m 
    where
        m.username like '%kim%' */ select
            membermapp0_.MEMBER_ID as member_i1_11_,
            membermapp0_.createdAt as createda2_11_,
            membermapp0_.createdBy as createdb3_11_,
            membermapp0_.updatedAt as updateda4_11_,
            membermapp0_.updatedBy as updatedb5_11_,
            membermapp0_.city as city6_11_,
            membermapp0_.street as street7_11_,
            membermapp0_.zipcode as zipcode8_11_,
            membermapp0_.LOCKER_ID as locker_15_11_,
            membermapp0_.TEAM_ID as team_id16_11_,
            membermapp0_.USERNAME as username9_11_,
            membermapp0_.WORK_CITY as work_ci10_11_,
            membermapp0_.WORK_STREET as work_st11_11_,
            membermapp0_.WORK_ZIPCODE as work_zi12_11_,
            membermapp0_.endDate as enddate13_11_,
            membermapp0_.startDate as startda14_11_ 
        from
            MemberMapping membermapp0_ 
        where
            membermapp0_.USERNAME like '%kim%'

2. Criteria 소개

  • 문자가 아닌 자바코드로 JPQL을 작성(JPQL 빌더 역할, JPA 공식 스펙)
  • (장점)동적쿼리 생성에 편리, 자바코드이기 때문에 컴파일 오류로 오타 등 발견 가능
  • (단점)코드 유지보수가 어려움(너무 복잡하고 실용성X)
    • 📌사실상 실무에서는 사용 X
    • 대신 QueryDSL(오픈소스 라이브러리) 사용 권장
  //Criteria 사용 준비
            CriteriaBuilder cb = em.getCriteriaBuilder();
            CriteriaQuery<MemberMapping> query = cb.createQuery(MemberMapping.class);

            //루트 클래스 (조회를 시작할 클래스)
            Root<MemberMapping> m = query.from(MemberMapping.class);

            //쿼리 생성
            CriteriaQuery<MemberMapping> cq = query.select(m);

            //동적쿼리 생성에 편리
            String username = "test";
            if (username != null) {
                cq = cq.where(cb.equal(m.get("username"),"kim"));
            }

            List<MemberMapping> resultList = em.createQuery(cq).getResultList();

3. 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();

4. 네이티브 SQL 소개

  • JPA가 제공하는 SQL을 직접 사용하는 기능
  • JPQL로 해결 불가한 특정 데이터베이스에 의존적인 기능
    • ex) 오라클의 CONNECT BY
  • 실무에서 사용도가 높지는 않음
String sql =
“SELECT ID, AGE, TEAM_ID, NAME FROM MEMBER WHERE NAME = ‘kim’";
List<Member> resultList =
em.createNativeQuery(sql, Member.class).getResultList();

5. JDBC API를 직접 사용, MyBatis, SpringJdbcTemplate 함께 사용

  • JPA를 사용하면서 JDBC 커넥션을 직접 사용하거나 스프링 JdbcTemplate, MyBatis 등을 함께 사용 가능
  • 단, 영속성 컨텍스트를 적절한 시점에 강제로 em.flush(); 해줘야 함
    • 기본적으로 flush는 commit 직전 혹은 entityManager 통해 query 날아가는 시점에 자동으로 실행
    • 하지만 직접 JDBC 커넥션을 얻어오는 등 JPA와 관련이 없는 행위를 할 때에는 flush가 되지 않으므로 결과가 X
    • JPA를 우회해서 SQL을 실행하기 직전에 영속성 컨텍스트를 수동으로 flush

0개의 댓글