본문 바로가기
Back-end/JPA 개념

34. JPQL - 다형성 쿼리, Entity 직접 사용, Named 쿼리

by devraphy 2022. 5. 7.

0. 개요

- 이번 포스팅에서는 유용한 JPA의 기능 몇 가지를 알아보도록 하자.

 

 

1. 다형성 쿼리

a) 다형성 쿼리란?

- 다형성 쿼리는 상속 관계에서 사용할 수 있는 기능이다.

- 부모 객체를 통해 특정 자식 객체를 조회할 때 사용하는 기능이다.

 

 

b) 다형성 쿼리 사용 방법

- 예를 들어, Food라는 부모 객체가 있고 하위에 Beverage, Snack이 있다고 해보자.

 

- Food 객체를 통해 Snack 객체를 조회하고 싶은 경우, 다음과 같은 JPQL을 작성할 수 있다.

SELECT f FROM Food f WHERE TYPE(f) IN(Snack);

 

- 위의 JPQL은 다음과 같은 SQL로 번역되어 DB에게 전달된다.

SELECT f FROM Food f WHERE f.DTYPE IN ('Snack');

 

 

c) TREAT()

- 다형성 쿼리와 연계되는 개념으로, 타입 다운 캐스팅 기능이다.

- 상속 관계에서 부모 객체를 특정 자식 객체의 타입으로 캐스팅할 때 사용한다.

- FROM, WHERE, SELECT 절에서 사용할 수 있다.

 

 

d) TREAT 사용 방법

- 예를 들어, Food라는 부모 객체가 있고 하위에 Beverage, Snack이 있다고 해보자.

- Snack 하위 객체의 이름이 '칙촉'과 일치하는 상위 객체 Food를 조회하려고 한다.

- 다음과 같이 JPQL을 작성할 수 있다.

SELECT f FROM Food f 
WHERE TREAT(f as Snack).NAME = '칙촉';

 

- 위에서 작성한 JPQL은 다음과 같은 SQL로 번역되어 DB에게 전달된다.

SELECT f.* FROM Food f
WHERE f.DTYPE = 'Snack' AND f.NAME = '칙촉';

 

 

2. Entity 직접 사용 

- 지금까지 JPQL을 작성할 때, 다음과 같이 Entity를 직접 명시하여 사용하였다.

SELECT COUNT(p) FROM Player p;

 

- 그렇다면 매개변수로 사용된 p는 어떤 값이 들어가는 것일까?

- 위의 JPQL은 다음과 같은 SQL로 번역되어 DB에게 전달된다.

SELECT COUNT(p.ID) FROM Player p;

 

- 다른 예시를 하나 더 살펴보자.

String query = "SELECT p FROM Player p WHERE p =: player";

List<Player> resultList = em.createQuery(query)
                            .setParameter("player", player);
                            .getResultList();

 

- 위에서 작성된 JPQL은 다음과 같은 SQL로 번역된다.

SELECT p.* FROM Player p WHERE p.ID = ?;

 

- 이처럼 JPQL에서 Entity를 직접 명시하면 해당 Entity의 기본 키(= Primary key)가 전달된다.

 

 

3. Named 쿼리 

a) Named 쿼리란?

- Named 쿼리란, 미리 정의하여 메서드처럼 재사용이 가능한 정적 JPQL이다.

- Named 쿼리는 Annotation을 이용하여 정의할 수 있다.

- 또는 XML에 정의하여 global 레벨로 사용할 수도 있다.

 

 

b) Named 쿼리의 장점 

- Named 쿼리는 Application 로딩 시점에서 쿼리가 검증된다는 장점이 있다.

- 또한 Application 로딩 시점에서 초기화되어 재사용이 가능하다는 장점이 있다.

 

 

c) Named 쿼리 설정 및 사용 방법  - Annotation

- Annotation을 사용하여 Named 쿼리를 정의할 때에는 Entity에 직접 정의한다.

- 다음 예시를 살펴보자.

@Entity

@NamedQuery(
      name = "Player.findPlayerName",
      query = "select p.name from Player p where p.id = :playerId")

public class Player {...}

 

- 위의 예시처럼, Annotation을 사용하여 Entity 레벨에 Named 쿼리를 정의할 수 있다.

- 정의된 Named 쿼리는 다음과 같이 사용할 수 있다.

String result = em.createQuery("Player.findPlayerName", Player.class)
                   .setParameter("playerId", 1L)
                   .getSingleResult();

 

 

d) Named 쿼리 설정 및 사용 방법  - XML

- XML에 정의할 때에는 다음과 같이 작성한다.

 

[META-INF/namedQueryPlayer.xml]

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" version="2.1">

   <named-query name="Player.findPlayerName">
      <query><![CDATA[
         select p
         from Player p
         where p.id = :playerId
      ]]></query>
   </named-query>
   
   <named-query name="Player.findAllPlayer">
      <query>select p from Player p</query>
   </named-query>
   
</entity-mappings>

 

 

- 작성한 XML 파일을 적용하기 위해서 persistence.xml에 다음과 같이 등록한다.

[META-INF/persistence.xml]

<persistence-unit name = "hellojpql">
   <mapping-file> META-INF/namedQueryPlayer.xml</mapping-file>
</persistence-unit>

 

 

e) Named 쿼리 사용 시 주의사항

- Named 쿼리는 XML이 항상 우선권을 가진다.

- Application 환경에 따라 다른 XML을 배포할 수 있다.

'Back-end > JPA 개념' 카테고리의 다른 글

JPA 개발 꿀팁  (0) 2022.05.25
35. JPQL - 벌크 연산  (0) 2022.05.08
33. JPQL - Fetch Join의 한계  (0) 2022.05.06
32. JPQL - Collection Fetch Join과 Distinct  (0) 2022.05.05
31. JPQL - Fetch Join 개념  (0) 2022.05.04

댓글