본문 바로가기
Backend/JPA

[JPA] JPA의 다양한 쿼리 방법 소개

by 2245 2023. 12. 24.

출처

https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 강의 - 인프런

현업에서 실제로 JPA로 개발을 하고 있습니다. 그런 입장에서보면 지금 작성하고 있는 코드들이 어떻게 작동하는지 이해하는데 큰 도움을 주는 강의입니다. 다음은 제가 느낀 이 강의의 장점들

www.inflearn.com

 

목차

     

     

    서론

    가장 단순하게 데이터를 조회하는 방법은 EntityManager.find(), 객체 그래프 탐색(a.getB())을 이용한 방법입니다. 

    하지만, 나이가 18살 이상인 모든 회원을 조회하는 것 같이 조건이 걸린 데이터 조회는 어떻게 해야 할까요?  

    이에 JPA는 다양한 쿼리 방법을 지원합니다. 종류와 특징에 대해 알아보겠습니다.

     

     

    JPQL

    • JPA는 테이블이 아닌 엔티티 객체를 중심으로 개발됩니다.
    • 문제는 검색을 할 때 테이블이 아닌 엔티티 객체를 대상으로 검색해야 합니다.
    • 모든 데이터베이스 데이터를 객체로 변환하여 검색하는 것은 불가능합니다. 
    • 조건을 통해 애플리케이션에서 필요한 데이터만 데이터베이스에서 불러오려면, 결국 검색 조건이 포함된 SQL이 필요합니다. 
    • 따라서 JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공합니다.

     

    특징

    String jpql = "select m From Member m where m.name like ‘%hello%'";
    List<Member> result = em.createQuery(jpql, Member.class)
                 			.getResultList();
    • SQL과 문법이 유사합니다. (ANSI 표준 SQL - SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원)
    • JPQL은 엔티티 객체를 대상으로 쿼리를 날립니다.
    • SQL은 데이터베이스 테이블을 대상으로 쿼리를 날립니다. 
    • JPQL로 작성한 쿼리는 SQL로 변환되어 실행됩니다. 
    • JPQL은 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 SQL 입니다.
    • SQL을 추상화했기 때문에 특정 데이터베이스 SQL에 의존하지 않습니다.

    [변환되어 실행된  SQL]

    select
      m.id as id,
      m.age as age,
      m.USERNAME as USERNAME,
      m.TEAM_ID as TEAM_ID
    from
      Member m
    where
      m.age>18

     

    ✔️JPQL은 엔티티 대상, SQL은 테이블 대상

     

     

     

    Criteria

    • 문자가 아닌 자바 코드로 JPQL을 작성할 수 있습니다.
    //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.createQuery(cq).getResultList();
    • 문자가 아닌 자바 코드로 작성함으로써, 오타 입력 시 컴파일 오류가 발생하고, 동적 쿼리 생성이 용이합니다.
    • JPQL 빌더 역할을 합니다.
    • JPA에서 제공하는 공식 기능입니다.
    • 단점: 너무 복잡하고 실용성이 없습니다. 
    • Criteria 대신에 QueryDSL 사용을 권장합니다.

     

     

    QueryDSL

    • 문자가 아닌 자바 코드로 JPQL을 작성할 수 있습니다.
    //JPQL: select m from Member m where m.age > 18
    JPAQueryFactory query = new JPAQueryFactory(em);
    QMember m = QMember.member;  //Member에 관한 SQL
    
    List<Member> list = query.selectFrom(m)
            .where(m.age.gt(18))
            .orderBy(m.name.desc())
            .fetch();
    • 문자가 아닌 자바 코드로 작성함으로써, 오타 입력 시 컴파일 오류가 발생하고, 동적 쿼리 생성이 용이합니다.
    • JPQL 빌더 역할을 합니다.
    • 단순하고 쉽습니다. (JPQL과 거의 비슷합니다. 따라서, JPQL만 잘 알아두면 간편하게 사용할 수 있습니다.)
    • 실무 사용을 권장합니다.

     

     

    네이티브 SQL

    • JPQL로 해결할 수 없는 특정 데이터베이스에 의존적인 기능을 제공할 떄 사용합니다.
    • 예) 오라클의 CONNECT BY 또는 특정 DB만 사용하는 SQL 힌트
    • JPA가 제공하는 SQL을 직접 사용하는 기능입니다. 
    String sql = “SELECT ID, AGE, TEAM_ID, NAME FROM MEMBER WHERE NAME = ‘kim’";
    List<Member> resultList = em.createNativeQuery(sql, Member.class).getResultList();

     

     

    JDBC 직접 사용, SpringJdbcTemplate 등

    • JPA를 사용하면서 JDBC 커넥션을 직접 사용하거나, 스프링 JdbcTemplate, 마이바티스 등도 함께 사용할 수 있습니다. 
    • 단, 필요한 시점에 영속성 컨텍스트 강제 플러시가 필요합니다.
    Member member = new Member();
    member.setUsername("member1");
    em.persist(member);
    
    //em.flush();    //강제 플러시
    
    dbconn.executeQuery("select * from member");  //flush를 하지 않으면, db에 Member 객체가 없다.