- 참조: 자바 ORM 표준 JPA 프로그래밍
- Named Query
여태까지는 JPQL 예제를 작성하면서 String 변수에 JPQL 을 완성하여 수행하였다. 이를 동적 쿼리라고 한다.
Mybatis 를 사용해본 경험이 있다면 보통 XML 에 특정 Query 를 선언해놓고 맵핑되는 파라미터만 변경하여 사용해본적이 있을 것이다. 이를 정적 쿼리 라고 한다. JPQL 도 XML 이나 어노테이션으로 정적 쿼리를 미리 작성해놓을 수 있다.
NamedQuery 는 어플리케이션 로딩 시점에 미리 JPQL 문법을 체크하여 파싱한다. 오류 파악도 용이하며 미리 파싱한 결과를 재사용하여 성능상 이점도 있다.
NamedQuery 는 @NamedQuery 어노테이션에 작성하는 방식과 XML 에 작성하는 2 가지 방식이 있다.
- @NamedQuery
어노테이션 방식으로 정적 쿼리를 작성하는 예제를 살펴보자.
@Entity
@NamedQuery(
name = "Member.findMemberByName",
query = "select m from Member m where m.name = :username"
)
public class Member extends DateMarkable{
@NamedQuery 는 query 에 수행될 JPQL 을 작성해준다. 그리고 name 으로 해당 query 이름을 붙여준다.
위의 예제에서 앞에 Member. 을 붙여준것은 특별한 기능이 있는것이 아니라 충돌 방지를 위해 엔티티명을 붙여주었다. Mybatis 에서도 xml 파일에 namespace 를 지정해주어 쿼리 이름의 중복을 방지해주는것과 비슷한 기조라고 생각하면 되겠다.
Member member1 = new Member();
member1.setName("Name#1");
em.persist(member1);
Member member2 = new Member();
member2.setName("Name#2");
em.persist(member2);
위와 같이 2 명의 Member 를 영속화 하고 아래처럼 JPQL 을 작성한다.
List<Member> members = em.createNamedQuery("Member.findMemberByName", Member.class)
.setParameter("username", "Name#1")
.getResultList();
members.forEach(member -> {
System.out.println("Member name: " + member.getName());
});
Hibernate:
/* Member.findMemberByName */ select
member0_.member_id as member_i1_6_,
member0_.insert_datetime as insert_d2_6_,
member0_.update_datetime as update_d3_6_,
member0_.city as city4_6_,
member0_.street as street5_6_,
member0_.zipcode as zipcode6_6_,
member0_.name as name7_6_
from
member member0_
where
member0_.name=?
Member name: Name#1
수행된 SQL 을 보면 JPQL 이 아니라 @NamedQuery 에 name 속성이 주석으로 나온다.
NamedQuery 를 사용할 때에는 엔티티 매니저의 createNamedQuery 메소드를 사용한다. 만약 NamedQuery 를 여러 개 사용하려면 @NamedQueries 어노테이션을 사용해준다.
@Entity
@NamedQueries({
@NamedQuery(
name = "Member.findMemberByName",
query = "select m from Member m where m.name = :username"),
@NamedQuery(
name = "Member.findMemberById",
query = "select m from Member m where m.id = :memberId")
})
public class Member extends DateMarkable{
- NamedQuery XML 정의
실제 프로젝트에서도 위의 예제처럼 간단한 JPQL 만 작성하면 좋겠지만 현실은 그렇지 않다. 멀티 라인을 지원하지 않는 언어라면 쿼리가 조금만 길어져도 파악이 상당히 힘들다.
이럴 경우에는 별도의 파일에 쿼리를 관리하는게 좋다. XML 에 NamedQuery 를 작성할 수 있다.
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" version="2.1">
<named-query name="Member.findByUsername">
<query><![CDATA[
select m
from Member m
where m.name = :username
]]>
</query>
</named-query>
</entity-mappings>
...........
<persistence-unit name="jpatest">
<mapping-file>META-INF/ormMember.xml</mapping-file>
ormMember.xml 에 named-query 를 작성한다음 persistence.xml 에 mapping-file 에 해당 파일 경로를 맵핑해준다. 그 후 createNamedQuery 를 이용하여 수행해주면 @NamedQuery 어노테이션과 동일하게 동작한다.
만약 @NamedQuery 와 xml 에서 같은 이름을 부여했다면 XML 우선권을 갖는다.
'Framework and Tool > JPA' 카테고리의 다른 글
JPA - 객체지향 쿼리 언어 - Criteria 쿼리 생성 (0) | 2021.08.05 |
---|---|
JPA - 객체지향 쿼리 언어 - Criteria (0) | 2021.08.04 |
JPA - 객체지향 쿼리 언어 - JPQL 다형성 쿼리 (0) | 2021.08.03 |
JPA - 객체지향 쿼리 언어 - JPQL 서브쿼리, 조건식 (0) | 2021.08.03 |
JPA - 객체지향 쿼리 언어 - JPQL 경로 표현식 (0) | 2021.08.02 |
댓글