https://docs.spring.io/spring-data/jpa/docs/2.7.7/reference/html/#specifications
Spring Data JPA - Reference Documentation
Example 109. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del
docs.spring.io
틀린 해석이나 내용을 찾으시면 알려주세요 감사합니다 🤓
5.1.5. Specifications
JPA 2에서는 프로그래밍 방식으로 쿼리를 작성할 수 있는 API가 도입되었다
조건을 작성하여 domain class에 대한 query의 where절을 정의한다
Spring Data JPA는 EricEvans의 저서 "Domain Driven Desigh" 의 개념을 가져왔고
JPA 기준 API로 제공한다.
JpaSpecificationExecutor 인터페이스로 저장소 인터페이스를 확장할 수 있다.
사용법
public interface CustomerRepository extends CrudRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {
…
}
The additional interface has methods that let you run specifications in a variety of ways.
List<T> findAll(Specification<T> spec);
Specification은 다음과 같은 interface로 정의된다
public interface Specification<T> {
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
CriteriaBuilder builder);
}
필요한 모든 조합에 대해 쿼리(메서드)를 선언할 필요 없이 결합하고
사용할 수 있는 엔터티 위에 확장 가능한 조건자 집합을 빌드하는 데 쉽게 사용할 수 있다.
public class CustomerSpecs {
public static Specification<Customer> isLongTermCustomer() {
return (root, query, builder) -> {
LocalDate date = LocalDate.now().minusYears(2);
return builder.lessThan(root.get(Customer_.createdAt), date);
};
}
public static Specification<Customer> hasSalesOfMoreThan(MonetaryAmount value) {
return (root, query, builder) -> {
// build query here
};
}
}
Customer_ 유형은 JPA 메타모델 생성기를 사용하여 생성된 메타모델 유형이다
따라서 Customer_.createdAt 식은 고객이 Date 유형의 createdAt 속성을 가지고 있다고 가정하고 진행한다
그 외에도 비즈니스 요구 사항 추상화 수준에 대한 몇 가지 기준을 표현하고 실행 가능한 사양을 만든다
클라이언트는 다음과 같이 사용할 수 있다.
Using a simple Specification
List<Customer> customers = customerRepository.findAll(isLongTermCustomer());
간단한 쿼리에서 Specification을 작성하지 않는 이유는 간단하다
Single Specification의 사용은 일반 쿼리 선언과 비교 하여 진가를 발휘하지못한다
Specification은 여러 Specifications 들을 만들 때 빛을 발한다
Combined Specifications
MonetaryAmount amount = new MonetaryAmount(200.0, Currencies.DOLLAR);
List<Customer> customers = customerRepository.findAll(
isLongTermCustomer().or(hasSalesOfMoreThan(amount)));
Specification instnace를 연결하고 결합하는 glue-code 방법을 제공한다
기존 구현과 결합하면 데이터 액세스 계층을 확장할 수 있다
'Web > DB' 카테고리의 다른 글
[SQL] 정규화(Normalization) (0) | 2023.03.05 |
---|---|
[Hibernate orm] 11. Fetching (0) | 2023.02.16 |
[Hibernate validator] 5. Grouping constraints (0) | 2023.02.06 |
[Hibernate validator] 6. Creating custom constraints (1) | 2023.02.02 |
[Hibernate orm] 2.7. Associations (1) | 2023.02.02 |