온 코딩

[Spring Boot] JPA - JPQL 사용하기 본문

복습 ARCHIVE/모델별 프로젝트

[Spring Boot] JPA - JPQL 사용하기

SummerON 2021. 7. 21. 22:48

JPQL : 객체지향쿼리

테이블이 아닌 객체로 검색하는 쿼리 , SQL을 추상화하기 때문에 특정 데이터베이스 SQL에 의존하지 않는다.

즉, 데이터베이스가 바뀌어도 문법이 바뀌지 않음!

JPQL로 작성한 쿼리를 JPA가 데이터베이스에 맞는 SQL로 변역하여 데이터베이스 조회!

 

+ JPA에서 데이터베이스를 조회하기 위해 사용할 수 있는 방법

 : Critia쿼리 ,  네이티브SQL , QueryDSL , JDBC 직접 접근

 

JPA에서 제공하는 메소드들로도 데이터베이스 접근이 가능하나 복잡한 쿼리를 작성할 수 없기 때문에 JPQL 등과 같은 다른 부수적인 방법 사용 

 

JPQL 문법

- select / update / delete문 사용 가능 

- SELECT / UPDATE는 직접 쿼리를 데이터베이스에 쓰는 벌크연산이기 때문에 영속성 컨텍스트와 실제 데이터베이스 차이가 있을 수 있음 - 만일 벌크연산과 다른 연산을 함께 하게 된다면 벌크 연산부터 수행해서 차이를 없애 주기!

- 대소문자 구분 

- 테이블/칼럼 이름이 아니라 엔티티/변수 이름을 사용

- 엔티티에 대한 별칭 필수로 사용 

 

특징 

1. 불러오는 값은 Object이다 

가져오는 컬럼값이 여럿일 경우, Object[]

 

2. 결과 조회 

- query.getResultList() : 결과를 컬렉션으로 반환

- query.getSingleList() : 결과값이 1개 일대 사용 

 

3. 파라미터 바인딩

- 변수 사용 시 - :변수명

ex) SELECT m FROM member m WHERE m.id = :id

- 변수 위치로 바인딩 - ?1 (첫번째 ?에 입력받는 값)

- 라이크 연산 - %입력값%

=> 같은 쿼리는 결과를 재사용하기 때문에 왠만하면 상수도 파라미터 바인딩을 통해 입력하기!

 

4. New 생성어

Object[]가 아닌 엔티티로 생성한 값을 바로 받아볼 수 있다

ex) SELECT NEW (클래스로케이션).MemberDTO(m.user, m.age, m.gender ) FROM Member m

 

5. 페이징 

- setFirstResult(int startPosition) : 조회 위치 부터 0

- setMaxResult(int maxResult) : 조회할 데이터 수 

 

6. 관계 조회  

- COUNT(Long) , MAX,MIN , AVG(Double), SUM 사용가능 

- Group by , Having 사용 가능 

- Order by 사용가능 

- DISTICT 사용가능 

 

7. 조인 

- SQL과 가장 다른 부분 

- 연관 필드를 사용해서 연관관계를 필수적으로 명시 

ex1 ) SELECT m FROM Member m INNER JOIN m.team t

ex2 ) SELECT t, m FROM Team t LEFT JOIN t.members m - 컬렉션 조인 ( 연관관계가 있는 경우)

조인할 때 ON 절을 자동 지원

 :  ex1 에서 ON m.id = t.id 를 자동 생성 

 

* 패치조인 

ex1 ) SELECT m FROM Member m INNER JOIN FETCH m.team

엔티티에 패치된 값들을 자동으로 조회 , 객체 그래프를 그대로 유지하면서 리턴 받음

 * 패치 - 일반 조인 테이블의 경우 결과를 반환할 때까지 연관관계를 고려하지 않는데, 패치를 설정하면 생성부터 연관관계 고려하게 됨. EAGER타입 패치는 반환 즉시 로딩을 하기 위해 쿼리를 한 번 더 시행 -> 이걸 막기위한 것 : LAZY 패치

- 패치조인은 엔티티에 정의된 글로벌 패치 전략보다 우선하기 때문에 글로벌을 LAZY 설정하고 필요할 때만 패치조인을 쓰게 되면 최적화에 적합!

- 한계 : 패치조인에는 별칭을 줄 수 없음 - 패치조인 대상은 SELECT, WHERE, 서브쿼리에 사용 불가 

        : 한 쿼리에 한번만 사용 가능 

        : 페이징 API 사용 불가 

 

8. 서브쿼리 

- WHERE, HAVING 절에서만 서브쿼리 사용 가능

- EXISTS , ALL ,ANY, SOME, IN 사용 가능 

SELECT * FROM MEMEBER m WHERE m.age > ALL(SELECT~ 서브쿼리)

 

9. 조건식 

종류 내용
문자 작은 따옴표 사이에 표현.
작음 따옴표를 표현하고 싶으면 작은 따옴표 2개(’’) 사용
‘HELLO’
‘She’'s ’
숫자 L(Long 타입 지정)
D(Double 타입 지정)
F(Float 타입 지정)
10L
10D
10F
날짜 DATE {d ‘yyyy-mm-dd’}
TIME {t ‘hh:mm:ss’}
TIMESTAMP {ts 'yyyy-mm-dd hh:mm:ss.f}
m.createDate = {d ‘2012-03-24’}
Boolean TRUE, FALSE  
Enum 패키지명을 포함한 전체 이름 com.joont.MemberType.Admin
엔티티 타입 엔티티의 타입을 표현함. 주로 상속과 관련해 사용. TYPE(m) = Member

 

 

아래와 같은 Github블로그를 참고하였음 

https://joont92.github.io/jpa/JPQL/

 

[jpa] JPQL

JPA에서 현재까지 사용했던 검색은 아래와 같다. 식별자로 조회 EntityManager.find() 객체 그래프 탐색 e.g. a.getB().getC() 하지만 현실적으로 이 기능만으로 어플리케이션을 개발하기에는 무리이다. 그

joont92.github.io

 

Comments