본문 바로가기
프로그래밍/Back-end

JPA 쿼리 JPQL 페이징 조인 서브쿼리

by @GodWin 2024. 10. 18.

-

 

-

안녕하세요? 오늘은, JPA의 쿼리 방법 중 하나인, JQPL에 대해 알아보도록 하겠습니다.

 

 

JPQL

(Java Persistence Query Language)

 

: 객체지향 쿼리 언어
: 테이블 대상이 아닌,엔티티를 대상으로 쿼리
: SQL을 추상화 > 특정 DB에 의존하지 않음
: JPQL은 결국 SQL로 변환



샘플 예시)

select 문 :: =
select_절
from_절
[where_절]
[groupby_절]
[having_절]
[orderby_절]

update_문 :: = update_절 [where_절]
delete_문 :: = delete_절 [where_절]

 

사용법

 

: 엔티티와 속성은 대소문자 구분이 필수
: JPQL 키워드는 대소문자 구분 불필요
: 엔티티 이름 사용
> 테이블 이름 X
: 별칭(Alias)은 필수 (as는 생략가능)
: 집합과 정렬 등의
Ansi SQL
모두 사용 가능
(count, sum, avg, max, min)

+
반환 타입이 명확할 때
: TypeQuery 사용

+
반환 타입이 미명확할 때
: Query 사용

 

TypedQuery<엔티티> query1 = em.createQuery("SELECT e FROM 엔티티 e", 엔티티.class);

Query query2 = em.createQuery("SELECT e.컬럼A, e.컬럼B FROM 엔티티 e");

// 반환 데이터가 다중건
List<엔티티> resultList1 = query1.getResultList();
List<엔티티> resultList2 = query2.getResultList();

// 반환 데이터가 단건
엔티티 result1 = query1.getSingleResult();
엔티티 result2 = query2.getSingleResult();


+

getResultList

: 결과가 하나 이상일 때 리스트 반환
> 없으면 빈 리스트 반환

+

getSingleResult

: 결과가 정확히 하나이고, 단일 객체 반환일 때 사용
> 결과가 없으면 NoResultException 발생
> 둘 이상이면 NonUniqueResultException 발생


-
데이터 바인딩

샘플 코드)

TypedQuery<엔티티> query1 = em.createQuery("SELECT e FROM 엔티티 e where e.컬럼A = :조건컬럼A", 엔티티.class);
query1.setParameter(조건컬럼A, 값);

// 반환 데이터가 다중건
List<엔티티> resultList1 = query1.getResultList();

// 반환 데이터가 단건
엔티티 result1 = query1.getSingleResult();

 

 

프로젝션


: 조회 절에 조회할 대상을 지정하는 것
: 엔티티, 임베디드 값타입, 스칼라 타입 대상

: DISTINCT로 중복 제거 가능

ex)
SELECT e FROM 엔티티 e
SELECT e.컬럼 FROM 엔티티 e
SELECT e.임베디드컬럼 FROM 엔티티 e
SELECT e.컬럼A, e.컬럼B FROM 엔티티 e


++
예를 들어서, Member 엔티티와 Team 엔티티가 존재하고, 연관관계가 설정되어있다고 가정할 때, 조회 할 대상의 반환타입을 Team으로 지정

샘플 코드)

TypedQuery<Member> query = em.createQuery("SELECT m.team FROM Member m", Team.class);

List<엔티티> resultList = query.getResultList();

 

 

페이징


: JPA는 페이징을 두가지 API로 추상화
: 각 DB에 맞게끔 자동 페이징 쿼리 생성 조회


+
사용법

: setFirstResult(int startPosition)

> 조회 시작 위치
> 0부터 시작

: setMaxResult(int maxResult)

> 조회할 데이터 수

샘플코드)

String jqpl = "SELECT e FROM 엔티티 e";

List<엔티티> resultList = em.createQuery(jqpl, 엔티티.class)
      .setFirstResult(1)
      .setMaxResult(10)
      getResultList();

System.out.println("resultList : " + resultList);

 

 

JOIN

(내부조인 / 외부조인 / 세타조인)

 

: 내부조인
> select e from 엔티티 e [INNER] join e.연관관계객체 s
: 기본으로 key값 매핑이 되고, 추가 조건은 on을 쓴다.
> select e from 엔티티 e [INNER] join e.연관관계객체 s on s.조건

: 외부조인
> select e from 엔티티 e left [OUTER] join e.연관관계객체 s
: 기본으로 key값 매핑이 되고, 추가 조건은 on을 쓴다.
>> select e from 엔티티 e [INNER] join e.연관관계객체 s on s.조건

: 세타조인
> select e, s from 엔티티 e, 조인엔티티 s where e.조건컬럼 = s.조건컬럼



+
Member엔티티와 Team엔티티가 서로, 연관관계가 셋팅되어있다고 가정하고, Team의 name컬럼에 '신'데이터가 포함 된 데이터를 조회

샘플코드)

// 내부 조인
String jqpl = "SELECT m FROM Member m INNER JOIN m.team t ON t.name = '%신%'";

List<Member> resultList = em.createQuery(jqpl, Member.class).getResultList();

System.out.println("resultList : " + resultList);


// 외부 조인
jqpl = "SELECT m FROM Member m LEFT OUTER JOIN m.team t ON t.name = '%신%'";

resultList = em.createQuery(jqpl, Member.class).getResultList();

System.out.println("resultList : " + resultList);

// 세타 조인
jpql = "SELECT m FROM Member m, Team t WHERE m.id = t.id AND t.name = '%신%'";

resultList = em.createQuery(jqpl, Member.class).getResultList();

System.out.println("resultList : " + resultList);

 

 

서브쿼리

: JPA에서는 WHERE / HAVING 절에서만 사용 가능
> 하이버네이트에서는 SELECT 절도 사용 가능

: FROM 절의 서브쿼리는 현재 JPQL에서 불가능
> JOIN으로 해결 추천



+

서브쿼리 지원 함수


: [NOT] EXISTS (서브쿼리)
> 서브쿼리에 결과가 존재하면 참
> ALL / ANY / SONE 추가 사용 가능
(모두 만족 / 조건 한개라도 만족) -> true

: [NOT] IN (서브쿼리)
> 서브쿼리 결과 중 하나라도 같은것이 있다면 참

샘플코드)

// 조건 절 서브쿼리 : exists 사용 예제
String jqpl = "SELECT e FROM 엔티티 e "
            + "WHERE EXISTS (SELECT s FROM e.연관관계객체 s WHERE s.컬럼조건)";

List<Member> resultList = em.createQuery(jqpl, Member.class).getResultList();

System.out.println("resultList : " + resultList);


// 조건 절 서브쿼리 : exists ALL 사용 예제
// s의 조건에 모두 부합하는 데이터가 존재할 시
jqpl = "SELECT e FROM 엔티티 e "
     + "WHERE m.조건 = ALL(SELECT s FROM e.연관관계객체 s WHERE s.컬럼조건)";

resultList = em.createQuery(jqpl, Member.class).getResultList();

System.out.println("resultList : " + resultList);


// 조건 절 서브쿼리 : exists ANY 사용 예제
// s의 조건에 하나라도 부합하는 데이터가 존재할 시
jqpl = "SELECT e FROM 엔티티 e "
     + "WHERE m.조건 = ANY(SELECT s FROM e.연관관계객체 s WHERE s.컬럼조건)";

resultList = em.createQuery(jqpl, Member.class).getResultList();

System.out.println("resultList : " + resultList);



 


※ JPA에서의 쿼리 방법에 대해서는, 아래 포스팅을 참조 부탁드리겠습니다.

https://logger-debug.tistory.com/entry/JPA-QueryDSL-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8CSQL-JDBC-MyBatis

 

JPA QueryDSL 네이티브SQL JDBC MyBatis

- -안녕하세요? 오늘은 JPA의 다양한 쿼리 방법에 대해서 알아보도록 하겠습니다. JPA에서는,JPQL ★★★JPQ CriteriaQueryDSL ★★★네이티브 SQLJDBC 직접 사용(MyBatis, SpringJdbcTemplate ...)등등 다양한 쿼

logger-debug.tistory.com

https://logger-debug.tistory.com/entry/JPA-JPQL-%ED%83%80%EC%9E%85-%ED%91%9C%ED%98%84%EC%8B%9D%EA%B3%BC-%EA%B8%B0%ED%83%80%EC%8B%9D-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%A1%B0%EA%B1%B4%EC%8B%9D%EA%B3%BC-%EA%B8%B0%EB%B3%B8-%ED%95%A8%EC%88%98

 

JPA JPQL 타입 표현식과 기타식 그리고 조건식과 기본 함수

- -안녕하세요? 오늘은 JPA의 JPQL 타입 표현식과 기타식 그리고 조건식과 기본 함수 에 대해서 알아보도록 하겠습니다.※ JPA에서의 쿼리 방법에 대해서는, 아래 포스팅을 참조 부탁드리겠습니다.

logger-debug.tistory.com

https://logger-debug.tistory.com/entry/JPA-JPQL-%EA%B2%BD%EB%A1%9C-%ED%91%9C%ED%98%84%EC%8B%9D

 

JPA JPQL 경로 표현식

- -안녕하세요? 오늘은 JPA에서 JPQL의 경로 표현식 에 대해 알아보도록 하겠습니다.※ JPA에서의 쿼리 방법에 대해서는, 아래 포스팅을 참조 부탁드리겠습니다.https://logger-debug.tistory.com/entry/JPA-Quer

logger-debug.tistory.com

https://logger-debug.tistory.com/entry/JPA-%EC%BF%BC%EB%A6%AC-%ED%8C%A8%EC%B9%98-%EC%A1%B0%EC%9D%B8-JPQL-FETCH-JOIN

 

JPA 쿼리 패치 조인 JPQL FETCH JOIN

- -안녕하세요? 오늘은 JPA에서 JPQL 패치(FETCH) 조인 에 대해 알아보도록 하겠습니다.※ JPA에서의 쿼리 방법에 대해서는, 아래 포스팅을 참조 부탁드리겠습니다.https://logger-debug.tistory.com/entry/JPA-Qu

logger-debug.tistory.com

https://logger-debug.tistory.com/entry/JPA-%EC%BF%BC%EB%A6%AC-JPQL-%EB%B2%8C%ED%81%AC-%EC%97%B0%EC%82%B0

 

JPA 쿼리 JPQL 벌크 연산

- -안녕하세요? 오늘은 JPA의 JPQL 중 벌크 연산에 대해 알아보도록 하겠습니다.-벌크 연산: 쿼리 한번으로, 여러 테이블 로우 변경: executeUpdate의 결과는 영향받은 엔티티 수를 반환: Update / Delete

logger-debug.tistory.com


오늘은, JPA의 쿼리 방법 중 하나인, JQPL에 대해 알아보았습니다.
그럼 오늘도 즐거운 하루 되시길 바라겠습니다.