프로젝트 git url | github.com/rtef23/JpaStudy |
필요 | 1. docker 2. docker-compose |
프로젝트 정보 | mysql : 5.7 - docker image java : 1.8 |
다형성 쿼리
TYPE
- 조회 대상을 특정 자식으로 한정
//Item 중에 Book, Movie를 조회해라
//[JPQL]
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)
- 특정 타입의 자식을 대상으로 하는 쿼리
//[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](위 2개의 JPQL모두 아래의 쿼리로 변환된다.)
SELECT COUNT(m.id)
FROM Member m
//[JPQL]
SELECT m
FROM Member m
WHERE m = :member
SELECT m
FROM Member m
WHERE m.id = :memberId
//[SQL](위 2개의 JPQL모두 아래의 쿼리로 변환된다.)
SELECT m.*
FROM Member m
WHERE m.id = ?
엔티티 직접 사용 - 외래키
//[JPQL]
SELECT m
FROM Member m
WHERE m.team = :team
SELECT m
FROM Member m
WHERE m.team.id = :teamId
//[SQL](위 2개의 JPQL모두 아래의 쿼리로 변환된다.)
SELECT m.*
FROM Member m
WHERE m.team_id = ?
Named 쿼리
- 미리 정의해서 이름을 부여해두고 사용하는 JPQL
- 정적 쿼리만 지원
- 어노테이션, XML에 정의하여 사용
- 어플리케이션 로딩 시점에 쿼리를 검증 및 초기화 * 재사용
@Entity
@NamedQuery(
name = "Member.findByUsername",
query = "select m from Member m where m.username = :username"
)
public class Member{
...
}
====================================================================
List<Member> results = entityManager
.createNamedQuery("Member.findByUsername", Member.class)
.setParameter("username", "회원-1")
.getResultList();
벌크 연산
- 재고가 10개 미만인 모든 상품의 가격을 10% 상승하려면?
- JPA의 변경 감지 기능으로 실행하려면 너무 많은 SQL이 실행된다.
- 재고가 10개 미만인 상품 리스트 조회
- 상품 엔티티의 가격을 10% 증가
- 트랜잭션 커밋 시점에 변경감지 동작
- JPA의 변경 감지 기능으로 실행하려면 너무 많은 SQL이 실행된다.
- 쿼리 1번으로 테이블의 여러 row를 변경
- UPDATE, DELETE 지원
Product product1 = new Product();
product1.setPrice(10);
String query = "update Product p" +
" set p.price = p.price * 1.1" +
" where p.stockAmount < :stockAmount";
//JPA에서 flush를 자동 호출하게 된다.
int resultCount = entityManager
.createQuery(query)
.setParameter("stockAmount", 10)
.executeUpdate();
//product1.price = 10로 벌크 연산 처리된 내용이 반영되지 않는다.
System.out.println("product1.price = " + product1.getPrice());
//위 이슈를 해결하기 위해서 clear API를 호출한다.(spring-data-jpa에서는 @Modifying으로 해결 가능)
entityManager.clear();
Product findProduct = entityManager.find(Product.class, product1.getId());
//product1.price = 11로 벌크 연산 처리된 내용이 반영된 내용으로 조회된다.
System.out.println("findProduct.price = " + findProduct.getPrice());
주의해야 할점
- 벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리하는 방식이기 때문에
영속성 컨텍스트에서 관리하는 엔티티와 실제 데이터가 맞지 않는 경우가 있다.- 벌크 연산을 먼저 수행하는 방법으로 해결
- 벌크 연상 수행후 영속성 컨텍스트를 초기화하는 방법으로 해결
'JPA' 카테고리의 다른 글
[JPA] 27. Fetch 조인 - 한계 (0) | 2021.02.16 |
---|---|
[JPA] 26. Fetch 조인 - 기본 (0) | 2021.02.11 |
[JPA] 25. 경로표현식 (0) | 2021.02.11 |
[JPA] 24. JPQL - 타입 표현, 기타식 (0) | 2021.01.31 |
[JPA] 23. JPQL - 조인, 서브 쿼리 (0) | 2021.01.31 |