JPQL 대량 작업 및 다형성 쿼리 및 명명된 쿼리

대량 운영

  • 특정 PK가 있는 엔터티의 업데이트/삭제를 제외한 모든 업데이트/삭제 쿼리.
  • 하나의 쿼리로 여러 테이블의 행을 변경합니다. (법인)
  • executeUpdate()의 결과는 영향을 받는 엔터티의 수를 반환합니다.
  • Insert 문은 Hibernate에서 지원됩니다. (.. 선택에 삽입)
// 재고가 10개 미만인 Product의 Price를 쿼리 한 번으로 10% 인상
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();

지침

대량 작업은 지속성 컨텍스트를 우회하고 DB를 직접 쿼리합니다. (데이터 무결성)

2가지 해결 방법

  • 대량 작업을 먼저 실행
  • 대량 작업 실행 후 지속성 컨텍스트 초기화(em.clear())

다형성 쿼리

유형

검색 대상은 특정 하위 클래스로 제한될 수 있습니다.

예를 들어 Item이 상위 클래스이고 Book, Movie 및 Song과 같은 하위 클래스가 있다고 가정합니다.

Item의 하위 클래스 중에서 Book과 Movie를 찾아봅시다.

String query = "select i from Item i where type(i) in (Book, Movie)";

처리(JPA 2.1)

  • Java의 typecasting과 유사합니다.
  • 상위 유형을 상속 트리의 특정 하위 유형으로 처리하는 데 사용됩니다.
  • FROM, WHERE, SELECT를 사용하십시오(Hibernate가 지원됨).

상위 유형 다운캐스팅의 예

String query = "select i from Item i where treat(i as Book).auther="Kim"";

명명된 쿼리 – 정적 쿼리

  • 엔티티 클래스에서 미리 정의된이름을 부여하여 사용하는 JPQL
  • 쿼리에 이름을 지정하고 이름으로 쿼리를 호출할 수 있습니다.
  • XML로 정의된 주석(XML이 항상 우선함)
  • 어플리케이션 로딩 시 초기화 후 재사용 (쿼리를 캐시하기 위해 SQL로 구문 분석)
  • 애플리케이션 로드 시 쿼리 유효성 검사 – 컴파일 타임 오류로 인한 쉬운 디버깅
  • 일반적으로 @Query는 엔터티에 대해 @NamedQuery보다 사용하기 더 편리하고 좋습니다.
// 엔티티 클래스에 정의
@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();

// 이름 없는 Named Query
public interface MemberRepository extends JPARepository<Member, Long> {
    @Query("select m from Member m where m.address = ?1")
    Member findByAddress(String address);
}

엔터티 직접 사용

JPQL에서 직접 엔터티를 사용하는 경우 SQL은 해당 엔터티의 기본 키 값을 사용합니다.

엔터티가 직접 사용되거나 매개변수로 전달되더라도 동일한 PK로 조회됩니다.

# 엔티티의 아이디를 사용
select count(m.id) from Member m

# 엔티티를 직접 사용
select count(m) from Member m

# 엔티티를 파라미터로 전달
select m from Member m where m = :member

# 식별자를 직접 전달
select m from Member m where m.id = :memberId