Spring/JPA

JPA 강의 7 - 객체지향 쿼리 언어 1 (기본 문법)

ummchicken 2022. 12. 19. 23:03

출처 : 자바 ORM 표준 JPA 프로그래밍 - 기본편

 

섹션 10. 객체지향 쿼리 언어1 - 기본 문법

💡 flush가 동작하는 때 : commit, query
(DB에 반영. em.persist()만 하면 DB 반영 안 됨

 

0. 객체지향 쿼리 언어(JPQL) 소개

  • JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어 제공
  • SQL과 문법 유사, SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원
  • JPQL은 엔티티 객체를 대상으로 쿼리
  • SQL은 데이터베이스 테이블을 대상으로 쿼리
  • 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
  • SQL을 추상화해서 특정 데이터베이스 SQL에 의존X
  • JPQL을 한마디로 정의하면 객체 지향 SQL
MyBatis의 장점 : 동적 쿼리를 마음대로 짤 수 있음

 

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

  • JPQL(거의 95% 정도 사용) ✔️
  • JPA Criteria
  • QueryDSL (거의 95% 정도 사용) ✔️
  • 네이티브 SQL
  • JDBC API 직접 사용, MyBatis, SpringJdbcTemplate 함께 사용 (5%)

 

0 - 2. QueryDSL 소개

  • 문자가 아닌 자바코드로 JPQL을 작성할 수 있음
  • JPQL 빌더 역할
  • 컴파일 시점에 문법 오류를 찾을 수 있음
  • 동적쿼리 작성 편리함
  • 단순하고 쉬움
  • 실무 사용 권장

 

1. JPQL(Java Persistence Query Language)

1 - 1. JPQL 소개

  • JPQL은 객체지향 쿼리 언어임.
    따라서 테이블을 대상으로 쿼리하는 것이 아니라 엔티티 객체를 대상으로 쿼리
  • JPQL은 SQL을 추상화해서 특정데이터베이스 SQL에 의존하지 않음
  • JPQL은 결국 SQL로 변환됨

 

1 - 2. JPQL 문법

  • select m from Member as m where m.age > 18
  • 엔티티와 속성은 대소문자 구분O (Member, age)
  • JPQL 키워드는 대소문자 구분X (SELECT, FROM, where)
  • 엔티티 이름 사용, 테이블 이름이 아님(Member)
  • 별칭은 필수(m) (as는 생략가능)

 

1 - 3. TypeQuery, Query

  • TypeQuery : _반환 타입_이 명확할 때 사용
  • Query : _반환 타입_이 명확하지 않을 때 사용
    TypedQuery<Member> query =
    em.createQuery("SELECT m FROM Member m", Member.class);
    Query query =
    em.createQuery("SELECT m.username, m.age from Member m");

 

1 - 4. 결과 조회 API

  • query.getResultList(): 결과가 하나 이상일 때, 리스트 반환
    • 결과가 없으면 빈 리스트 반환
  • query.getSingleResult(): 결과가 정확히 하나, 단일 객체 반환
    • 결과가 없으면: javax.persistence.NoResultException (예외 터짐)
    • 둘 이상이면: javax.persistence.NonUniqueResultException (예외 터짐)

 

1 - 5. 프로젝션

  • SELECT 절에 조회할 대상을 지정하는 것
  • 프로젝션 대상 : 엔티티, 임베디드 타입, 스칼라 타입 (숫자, 문자등 기본 데이터 타입)
  • DISTINCT로 중복 제거

 

1 - 6. 페이징 API

  • JPA는 페이징을 다음 두 API로 추상화
    1. setFirstResult(int startPosition) : 조회 시작 위치 (0부터 시작)
    2. setMaxResults(int maxResult) : 조회할 데이터 수

 

1 - 7. 조인

  • 내부 조인:
    SELECT m FROM Member m [INNER] JOIN m.team t
  • 외부 조인:
    SELECT m FROM Member m LEFT [OUTER] JOIN m.team t
  • 세타 조인:
    select count(m) from Member m, Team t where m.username = t.name

 

1 - 8. 조인 - ON 절

  • ON절을 활용한 조인 (JPA 2.1부터 지원)
    1. 조인 대상 필터링
      • 예) 회원과 팀을 조인하면서, 팀 이름이 A인 팀만 조인
      JPQL:
      SELECT m, t FROM Member m LEFT JOIN m.team t on t.name = 'A'
      SQL:
      SELECT m., t. FROM
      Member m LEFT JOIN Team t ON m.TEAM_ID=t.id and t.name='A'
    2. 연관관계 없는 엔티티 외부 조인 (하이버네이트 5.1부터)
      • 예) 회원의 이름과 팀의 이름이 같은 대상 외부 조인
      JPQL:
      SELECT m, t FROM
      Member m LEFT JOIN Team t on m.username = t.name
      SQL:
      SELECT m., t. FROM
      Member m LEFT JOIN Team t ON m.username = t.name