BACK/JPA

[JPA] TIL 9일차 - JPA 의 다양한 쿼리 방법(JPQL, JPA Criteria, QueryDSL 등)

연듀 2024. 4. 5. 18:01

 

 

JPA는 다양한 쿼리 방법(JPQL, JPA Criteria, QueryDSL...)을 지원한다.

대부분 jpql로 해결이 되지만, 어쩌다 안될 경우에는 네이티브 SQL이나 MyBatis, SpringJdbcTemplate를 쓰면 된다.

 

 

JPQL 소개

 

JPA를 사용하면 엔티티 객체를 중심으로 개발하게 되고, 검색할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색한다.

이 때 모든 데이터베이스를 메모리에 올려 객체로 변환해 검색하는것은 말이 안된다.

 

애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 있는 SQL이 필요하다.

이런 문제를 해결하기 위해 JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공한다.

 

SQL은 DB 테이블을 대상으로 쿼리하는 반면, JPQL은 엔티티 객체를 대상으로 쿼리한다.

JPQL을 짜면, SQL로 번역이 되어 실행된다.

 

List<Member> result = em.createQuery("select m from Member m where m.username like '%kim%'", Member.class).getResultList();

for (Member member : result) {
    System.out.println("member.getUsername() = " + member.getUsername());
}

 

 

/* select
        m 
    from
        Member m 
    where
        m.username like '%kim%' */
        select
            m1_0.MEMBER_ID,
            m1_0.INSERT_MEMBER,
....

 

 

주석으로 JPQL쿼리가 나가고, 실제 SQL문이 나간다.

 

JPQL 특징

  • 객체를 대상으로 검색하는 객체 지향 쿼리
  • SQL을 추상화해서 특정 데이터베이스 SQL에 의존 X
  • 객체 지향 SQL

 

Criteria

 

동적 쿼리를 위해 사용할 수 있다.

컴파일 시점에 오류를 체크할 수 있다.

문자가 아닌 자바 코드로 JPQL을 작성할 수 있다.

JPQL 빌더 역할을 하는 JPA 공식 기능

 

// 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();

 

 

단점으로 유지보수가 어렵기 때문에 실무에서 잘 사용하지 않는다.

복잡하고 실용성이 없기 때문에 QueryDSL 사용을 권장한다.

 

 

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

 

네이티브 SQL

JPA가 제공하는 SQL을 직접 사용하는 기능

JPQL로 해결할 수 없는 특정 데이터베이스에 의존적인 기능 ex) 오라클 CONNECT BY, 특정 DB만 사용하는 SQL 힌트

쿼리를 만들 때 DB에 flush가 된다.

 

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 커넥션을 직접 사용하거나 SpringJdbcTemplate, MyBatis 함께 사용 가능

단, 연속성 컨텍스트를 적절한 시점에 강제로 플러시 해야 한다.

ex) SQL을 실행하기 전에 영속성 컨텍스트 수동 플러시

 

 

 


 

 

인프런 자바 ORM 표준 JPA 프로그래밍 - 기본편을 수강하고 정리한 글입니다.

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