10.1 객체지향 쿼리 소개

ORM을 사용하면 데이터베이스 테이블이 아닌 엔티티 객체를 대상으로 개발.
검색도 테이블이 아닌 엔티티 객체를 대상으로 하는 방법이 필요.

종류 설명
SQL 데이타베이스 테이블을 대상으로 하는 데이터 중심의 쿼리
JPQL 엔티티 객체를 대상으로 하는 객체지향 쿼리.

◉ JPQL

JPA는 JPQL을 사용하면 이를 분석하여 SQL을 만들어 데이터베이스를 조회.
이 조회한 결과로 엔티티 객체를 생성해서 반환.

◉ JPA가 공식 지원하는 기능

객체지향 쿼리 설명
JPQL Java Persistence Query Language
Criteria 쿼리 JPQL을 편하게 작성하도록 도와주는 API, 빌더 클래스 모음
네이티브 SQL JPA에서 JPQL 대신 직접 SQL을 사용

◉ 다른 객체지향 쿼리

객체지향 쿼리 설명
QueryDSL JPQL을 편하게 작성하도록 도와주는 빌더 클래스 모음. 비표준 오픈소스 프레임워크
JDBC 직접 사용, MyBatis 등등 직접 사용 가능

10.1.1 JPQL 소개

JPQL(Java Persistence Query Language)은 엔티티 객체를 조회하는 객체지향 쿼리다.
JPQL은 SQL을 추상화해서 특정 데이트베이스에 의존하지 않는다.
JPQL은 SQL보다 간결하다.

회원 엔티티

@Entity(name = "Member")
public class Member {

    @Column(name = "name")
    private String username;
    // ...
}

JPQL 사용 예

// 쿼리 생성
String jpql = "select m from Member as m where m.username = 'kim'";
List<Member> resultList = 
        em.createQuery(jpql, Member.class).getResultList();

실행된 SQL

select
    member.id as id,
    member.age as age,
    member.team_id as team,
    member.name as name
from 
    Member mbmer
where
    member.name = 'kim'

10.1.2 Criteria 쿼리 소개

Criteria는 JPQL을 생성하는 빌더 클래스.
JPA 2.0부터 Criteria 지원.

장점

  • 컴파일 시점에 오류를 발견할 수 있다.
  • IDE를 사용하면 코드 자동완성을 지원한다.
  • 동적 쿼리를 작성하기 편하다.

Criteria 쿼리 예

// Criteria 사용 준비
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> query = cb.creatQuery(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();

메타모델 API

Member 엔티티 클래스로부터 Member_라는 Criteria 전용 클래스를 생성. -> 메타모델.

메타모델 사용 전 사용 후
m.get("username") m.get(Member_.username)

단점

  • 모든 장점을 상쇄할 정도로 복잡하고 장황하다.
  • 사용하기 불편하다.
  • 코드를 읽기 어렵다.

QueryDSL 소개

QueryDSL도 Criteria처럼 JPQL 빌더 역할을 한다.
JPA 표준은 아님

QueryDSL 장점

  • 단순하고 사용하기 쉽다.
  • 스프링 데이터 프로젝트에서 지원.

QueryDSL 코드

//준비
JPAQuery query = new JPAQuery(em);
QMember member = QMember.member;

//쿼리, 결과조회
List<Member> members = 
        query.from(member)
        .where(member.username.eq("kim"))
        .list(member);

QueryDSL도 쿼리 전용 클래스를 만들어야 한다. QMember는 Member 엔티티 클래스를 기반으로 생성한 QueryDSL 쿼리 전용 클래스.

10.1.4 네이티브 SQL 소개

JPA는 SQL을 직접 사용할 수 있는 기능을 지원. -> 네이티브 SQL

네이티브 SQL 단점

특정 데이터베이스에 의존하는 SQL 작성
데이터베이스를 변경하면 네이티브 SQL도 수정.

네이티브 SQL 코드

직접 작성한 SQL을 데이터베이스에 전달.

String sql = "SELECT ID, AGE, ITEM_ID, NAME FROM MEMBER WHERE NAME = 'kim'";
List<Member> resultList = 
    em.createNativeQuery(sql, Member.class).getResultList();

10.1.5 JDBC직접 사용, MyBatis 같은 SQL 매퍼 프레임워크 사용

JPA는 JDBC 커넥션을 얻는 API를 제공하지 않음.
JPA 구현체가 제공하는 방법을 사용해야 함.

하이버네이트 JDBC 획득

Session session = entityManager.unwrap(Session.class);
session.doWork(new Work() {

    @Override
    public void execute(Connection connection) throws SQLExcetion {
        // work ...
    }
});
  • JPA를 우회해서 데이터베이스에 접근.
    • JPA가 전혀 인식하지 못함.
  • JDBC나 마이바티스를 JPA와 함께 사용하려면 영속성 컨텍스트를 적절한 시점에 강제로 플러시 해야 함.
  • SQL을 실행하기 직전에 영속성 컨텍스트를 수동으로 플러시 해야 함.

results matching ""

    No results matching ""