[자바 ORM 표준 JPA 프로그래밍 - 기본편] 11-4강~7강
https://inf.run/2zDo 강의를 수강하고 작성하는 게시물입니다.
1. 다형성 쿼리
1.1. TYPE
조회 대상을 특정 자식으로 한정
아래는 Item 중에 Book, Movie를 조회하는 쿼리이다.
-- jpql
select i from Item i
where type(i) IN (Book, Movie)
-- sql
select i from i
where i.DTYPE in ('B', 'M')
1.2. TREAT
JPA 2.1 이상에서 사용가능하다.
자바의 타입 캐스팅과 유사하다.
상속 구조에서 부모 타입을 특정 자식 타입으로 다룰 때 사용한다.
FROM, WHERE, SELECT 중에서 사용할 수 있다.
아래는 부모인 Item과 자식 Book일 경우 사용 예시이다.
[JPQL]
select i from Item i
where treat(i as Book).auther = 'kim'
[SQL]
select i.* from Item i
where i.DTYPE = 'B' and i.auther = 'kim'
위처럼 다운 캐스팅 처럼 쓸 수 있다.
2. 엔티티 직접 사용
2.1. 기본 키 값
JPQL에서 엔티티를 직접 사용하면 SQL에서 해당 엔티티의 기본키 값을 사용한다.
[JPQL]
select count(m.id) from Member m
-- 엔티티의 아이디를 사용
select count(m) from Member m
-- 엔티티를 직접 사용
select count(m.id) as cnt from Member m
기본키 값을 이용하는 방법은 아래 두 방법이 있다.
2.1.1. 엔티티를 파라미터로 전달
String jpql = “select m from Member m where m = :member”;
List resultList = em.createQuery(jpql)
.setParameter("member", member)
.getResultList();
2.1.2. 식별자를 직접 전달
String jpql = “select m from Member m where m.id = :memberId”;
List resultList = em.createQuery(jpql)
.setParameter("memberId", memberId)
.getResultList();
2.1.3. 두 예시의 실행결과
두 방법 모두 실행된 SQL이 아래와 같다.
select m.* from Member m where m.id=?
실행된 SQL이 같은 이유는 엔티티가 DB로 넘어가면 구분하는 과정이 PK이므로 같을 수 밖에 없다.
2.2. 외래 키 값
Team team = em.find(Team.class, 1L);
String qlString = “select m from Member m where m.team = :team”;
List resultList = em.createQuery(qlString)
.setParameter("team", team)
.getResultList();
String qlString = “select m from Member m where m.team.id = :teamId”;
List resultList = em.createQuery(qlString)
.setParameter("teamId", teamId)
.getResultList();
3. Named 쿼리
미리 엔티티에 쿼리이름을 부여하여 사용할 수 있다.
@Entity
@NamedQuery(
name = "Member.findByUsername",
query="select m from Member m where m.username = :username")
public class Member {
...
}
List<Member> resultList =
em.createNamedQuery("Member.findByUsername", Member.class)
.setParameter("username", "회원1")
.getResultList();
위와 같이 사용하면 어떤 메리트가 있을까?
- 미리 정의해서 이름을 부여해두고 사용하는 JPQL
- 정적쿼리(동적 불가)
- 어노테이션, XML에 정의
- 애플리케이션 로딩 시점에 초기화 후 재사용
- 애플리케이션 로딩 시점에 쿼리를 검증
정적쿼리라 변하지 않는데 JPA나 Hibernate같은 애들이 SQL로 파싱을 하고 캐시에 저장한다.
애플리케이션 로딩 시점에 쿼리를 검증하는 기능이 가장 막강하다. 쿼리를 잘못 쓸 경우 쿼리가 잘못되었다는 오류가 발생한다.
Spring data JPA에서 Repository에 쿼리문을 어노테이션으로 쓸 수 있는데 자동으로 Named 쿼리로 등록을 해준다.
강사님은 개인적으로 Named 쿼리를 쓰는건 비추천하고 결국 실무에서는 Spring data JPA를 사용하게 될거라고 말하셨다.
댓글 남기기