springframework/Spring Data JPA

Spring Data JPA : Specifications

Jungsoomin :) 2020. 11. 19. 17:11

Specifications

  • QueryDSL 의 Predicate와 유사 함.
  • 사용방법 다소 복잡.
  • Pageable 사용가능, 원하는 조건 저장가능, Static Import 로 코드 가독성 상승 가능

적용방법

  • hibernate-jpa model generator 의존성 추가
<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-jpamodelgen</artifactId>
</dependency>
  • 인텔리제이 기준 , Annotation Processor 설정란의 Processor 등록 란 > org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor 등록
  • maven 을 통해 컴파일을 진행하면 generate-source 폴더에 Entity 에 대한 클래스가 생성 됨 (QueryDSL 과 같다.)
  • maven package 시 문제가 일어나지 않게 메이븐 플러그인 등록 필요
 <plugin>
                <groupId>org.bsc.maven</groupId>
                <artifactId>maven-processor-plugin</artifactId>
                <version>2.0.5</version>
                <executions>
                    <execution>
                        <id>process</id>
                        <goals>
                            <goal>process</goal>
                        </goals>
                        <phase>generate-sources</phase>
                        <configuration>
                            <processors>
                                <processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
                            </processors>
                        </configuration>
                    </execution>
                </executions>
                    <dependencies>
                        <dependency>
                            <groupId>org.hibernate</groupId>
                            <artifactId>hibernate-jpamodelgen</artifactId>
                            <version>${hibernate.version}</version>
                        </dependency>
                    </dependencies>
</plugin>

사용 방법

  • 사용할 Repository 인터페이스는 JpaSpecificationExecutor<Domain> 를 상속한다. ( QueryDSL 의 QuerydslPredicateExecutor<Domain> 상속과 같음 )
public interface CommentRepository extends JpaRepository<Comment,Long>, JpaSpecificationExecutor<Comment> {
}

조건 정의는 클래스를 만들어 정의한다.

  • Specification<Domain> 을 리턴하는 메서드를 정의
  • Root 는 도메인클래스를 의미 
  • Processor 로 만든 클래스를 이용하여 프로퍼티를 제시한다.
  • CriteriaBuiler 의 정적메서드는 조건을 의미한다.
  • 함수형 인터페이스이므로 람다 사용가능.
  • Pageable 운용 가능
public class CommentSpec {

    public static Specification<Comment> isBest(){
        return new Specification<Comment>() {
            @Override
            public Predicate toPredicate(Root<Comment> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.isTrue(root.get(Comment_.best));
            }
        };
    }

    public static Specification<Comment> isGood(){
        return new Specification<Comment>() {
            @Override
            public Predicate toPredicate(Root<Comment> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                // Comment 엔티티의 up 컬럼이 10보다 >= 이냐
                return criteriaBuilder.greaterThanOrEqualTo(root.get(Comment_.up), 10);
            }
        };
    }
}

// 테스트 코드
	@Test
    public void testSpecification(){

        final Page<Comment> all = commentRepository.findAll(CommentSpec.isBest().and(CommentSpec.isGood()), PageRequest.of(0, 10));
    }
    
/// 만들어진 쿼리
Hibernate: 
    select
        comment0_.id as id1_1_,
        comment0_.best as best2_1_,
        comment0_.comment as comment3_1_,
        comment0_.down as down4_1_,
        comment0_.post_id as post_id7_1_,
        comment0_.title as title5_1_,
        comment0_.up as up6_1_ 
    from
        comment comment0_ 
    where
        comment0_.up>=10 
        and comment0_.best=1 limit ?

'springframework > Spring Data JPA' 카테고리의 다른 글

Spring Data JPA : Transaction  (0) 2020.11.19
Spring Data JPA : Query By Example  (0) 2020.11.19
Spring Data JPA : Projection  (0) 2020.11.19
Spring Data JPA : Entity Graph  (0) 2020.11.19
Spring Data JPA : Update 쿼리  (0) 2020.11.18