728x90
다형성 쿼리
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’)
TREAT
자바의 타입 캐스팅과 유사하다.
상속 구조에서 부모 타입을 특정 자식 타입으로 다룰 때 사용한다.
FROM, WHERE, SELECT(하이버네이트 지원) 사용한다.
예) 부모인 Item과 자식 Book이 있다.
[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’
엔티티 직접 사용
JPQL에서 엔티티를 직접 사용하면 SQL에서 해당 엔티티의 기본 키 값을 사용한다.
[JPQL]
select count(m.id) from Member m //엔티티의 아이디를 사용
select count(m) from Member m //엔티티를 직접 사용
[SQL](JPQL 둘다 같은 다음 SQL 실행)
select count(m.id) as cnt from Member m
기본 키 값
(1) 엔티티를 파라미터로 전달
String jpql = “select m from Member m where m = :member”;
List resultList = em.createQuery(jpql)
.setParameter("member", member)
.getResultList();
(2) 식별자를 직접 전달
String jpql = “select m from Member m where m.id = :memberId”;
List resultList = em.createQuery(jpql)
.setParameter("memberId", memberId)
.getResultList();
(1), (2)에서 실행된 SQL
select m.* from Member m where m.id=?
외래 키 값
(1) 엔티티를 파라미터로 전달
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();
(2) 식별자를 직접 전달
String qlString = “select m from Member m where m.team.id = :teamId”;
List resultList = em.createQuery(qlString)
.setParameter("teamId", teamId)
.getResultList();
(1), (2)에서 실행된 SQL
select m.* from Member m where m.team_id=?
Named 쿼리
미리 정의해서 이름을 부여해두고 사용하는 JPQL
- 정적 쿼리만 가능하다.
- 어노테이션, XML에 정의한다.
- 애플리케이션 로딩 시점에 초기화 후 재사용한다.
- 애플리케이션 로딩 시점에 쿼리를 검증한다.
- XML이 항상 우선권을 가진다.
- 애플리케이션 운영 환경에 따라 다른 XML을 배포할 수 있다.
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();
-XML
// [META-INF/persistence.xml]
<persistence-unit name="jpabook" >
<mapping-file>META-INF/ormMember.xml</mapping-file>
//[META-INF/ormMember.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="Member.findByUsername">
<query><![CDATA[
select m
from Member m
where m.username = :username
]]></query>
</named-query>
<named-query name="Member.count">
<query>select count(m) from Member m</query>
</named-query>
</entity-mappings>
벌크 연산
예) 재고가 10개 미만인 모든 상품의 가격을 10% 상승하려면?
문제점: JPA 변경 감지 기능으로 실행하려면 너무 많은 SQL 실행이 일어난다.
1. 재고가 10개 미만인 상품을 리스트로 조회
2. 상품 엔티티의 가격을 10% 증가
3. 트랜잭션 커밋 시점에 변경감지가 동작
변경된 데이터가 100건이라면 100번의 SQL 실행
이럴 때 벌크 연산이 필요하다!
벌크 연산은..
- 쿼리 한 번으로 여러 테이블 ROW 변경(엔티티)
- executeUpdate()의 결과는 영향받은 엔티티 수 반환
- UPDATE, DELETE, INSERT(하이버네이트 지원) 지원
String qlString = "update Product p " +
"set p.price = p.price * 1.1 " +
"where p.stockAmount < :stockAmount";
int resultCount = em.createQuery(qlString)
.setParameter("stockAmount", 10)
.executeUpdate();
벌크 연산 주의 사항
벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리
- 벌크 연산을 먼저 실행하거나
- 벌크 연산 수행 후 영속성 컨텍스트 초기화하자.
728x90
'💻dev > 🌱Java+Spring' 카테고리의 다른 글
Spring Data JPA | @Query, 값, DTO 조회하기 (0) | 2023.05.09 |
---|---|
Spring Data JPA | 마법같은 쿼리 메소드 기능과 @Query (0) | 2023.05.08 |
JPA | JPQL 중급 문법 뿌시기 - 페치 조인(fetch join) (0) | 2023.05.04 |
JPA | JPQL 중급 문법 뿌시기 - 경로 표현식, 명시적 조인 vs 묵시적 조인 (0) | 2023.05.04 |
JPA | JPQL 문법 뿌시기 - 타입 표현, 조건식, 기본 함수 (0) | 2023.05.04 |