JVM/JPA

JPQL 다형성 쿼리, 사용자 정의 함수, Named 쿼리

kyoulho 2023. 6. 28. 17:57

다형성 쿼리

예제 코드

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item {

    @Id
    @GeneratedValue
    @Column(name = "ITEM_ID")
    private Long id;

    private String name;
    private int price;
}

@Entity
@DiscriminatorValue("B")
@PrimaryKeyJoinColumn(name = "BOOK_ID")
public class Book extends Item{
    private String author;
    private String isbn;
}

 

TYPE

엔티티의 상속 구조에서 조회 대상을 특정 자식 타입으로 한정할 때 사용한다.

JPQ
SELECT i FROM Item i
WHERE TYPE(i) IN (Book, Movie)

SQL
SELECT i FROM Item i
WHERE i.DTYPE IN ('B', 'M')

 

TREAT(JPA 2.1)

자바의 형변환이라고 생각하면 된다.

JPA 표준은 FROM, WHERE 절에서 사용할 수 있지만, 하이버네이트는 SELECT 절에서도 사용할 수 있다.

JPQL
SELECT i FROM Item i WHERE TREAT(i AS Book).author = 'kim'

SQL
SELECT i.* From Item i
WHERE
	i.DTYPE='B'
    AND i.author='kim'

 

사용자 정의 함수 호출(JPA 2.1)

하이버네이트 구현체를 사용하면 방언 클래스를 상속해서 구현하고 사용할 데이터베이스 함수를 미리 등록해야 한다.

public class MyH2Dialect extends H2Dialect {
    public MyH2Dialect() {
    // concat 함수를 add_string이란 이름에 사용자함수로 등록했다
        registerFunction("add_string",
                new StandardSQLFunction("concat", StandardBasicTypes.STRING));
    }
}

// 프로퍼티 등록
spring.jpa.properties.hibernate.dialect=com.example.jpastudy.MyH2Dialect

// 사용
SELECT group_concat(i.name,'님') FROM Item i

 

Named 쿼리: 정적 쿼리

동적 쿼리

  • em.createQuery("select..")처럼 JPQL을 문자로 완성해서 직접 넘기는 것을 동적 쿼리라 한다. 런타임에 특정 조건에 따라 JPQL을 동적으로 구성할 수 있다.

 

정적 쿼리

  • 미리 정의한 쿼리에 이름을 부여해서 필요할 때 사용할 수 있는데 이것을 Named 쿼리라 한다. Named 쿼리는 한 번 정의하면 변경할 수 없는 정적인 쿼리다.
  • 애플리케이션 로딩 시점에 JPQL 문법을 체크하고 미리 파싱 해준다. 따라서 오류를 빨리 확인할 수 있고, 사용하는 시점에는 파싱 된 결과를 재사용하므로 성능상 이점도 있다.
  • 변하지 않는 정적 SQL이 생성되므로 조회 성능 최적화에도 도움이 된다.
  • Spring Data JPQ의 @Query를 사용하는 것을 권장한다.
@Entity
@NamedQueries({
        @NamedQuery(
                name = "Member.findByUsername",
                query = "SELECT m FROM Member m WHERE m.username = :username")})
public class Member {
    @Id
    private Long id;
    private String username;
}

// 사용
List<Member> resultList = em.createNamedQuery("Member.findByUsername", Member.class)
				.setParameter("username","회원1")
				.getResultList();

'JVM > JPA' 카테고리의 다른 글

네이티브 SQL  (0) 2023.06.30
QueryDSL  (0) 2023.06.28
JPQL 조건식  (0) 2023.06.28
JPQL 서브쿼리  (0) 2023.06.26
JPQL 조인과 페치조인  (0) 2023.06.25