스프링 데이터 JPA-21.Specifications


스프링 데이터 JPA: Specifications

에릭 에반스의 책 DDD에서 언급하는 Specification 개념을 차용 한 것으로 QueryDSL의 Predicate와 비슷합니다.

설정 하는 방법

  • ttps://docs.jboss.org/hibernate/stable/jpamodelgen/reference/en-US/html_single/
  • 의존성 설정
  • 플러그인 설정
  • IDE에 애노테이션 처리기 설정
  • 코딩 시작
          <dependency>
              <groupId>org.hibernate</groupId>
              <artifactId>hibernate-jpamodelgen</artifactId>
          </dependency>
    
              <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>
    

이후
인텔리j Preference
annotaion processor 탭
enable annotation processing 체크
annotaion processor 추가
org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor 입력

이후에
generated-sources 안에 클래스가 생긴 걸 볼 수 있다.
혹시나 적용이 안되면, 해당 클래스들도 적용시켜 준 후.(프로젝트 스트럭쳐)

1.JpaSpecificationExecutor

public interface CommentRepository extends JpaRepository<Comment, Long>, JpaSpecificationExecutor<Comment>  {

2.Specs 정의

public class CommentSpecs {

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

    public static Specification<Comment> isGood(){
        return new Specification<Comment>() {
            @Override
            public Predicate toPredicate(Root<Comment> root,
                                         CriteriaQuery<?> query,
                                         CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.greaterThanOrEqualTo(root.get(me.jaeuk.recentjpa.comment.Comment_.up), 10);
            }
        };
    }

테스트

    @Test
    public void specs(){
        //commentRepo.findAll(CommentSpecs.isBest().or(CommentSpecs.isGood()));

        Page<Comment> page =
                commentRepo.findAll(CommentSpecs.isBest().or(CommentSpecs.isGood()), PageRequest.of(0, 10));
    }

실행결과

Hibernate: 
    select
        comment0_.id as id1_0_,
        comment0_.best as best2_0_,
        comment0_.comment as comment3_0_,
        comment0_.down as down4_0_,
        comment0_.post_id as post_id6_0_,
        comment0_.up as up5_0_ 
    from
        comment comment0_ 
    where
        comment0_.up>=10 
        or comment0_.best=1 limit ?

상당히 괜찮은 방법 같다.
스펙만 잘 정의한다면 코드도 간결하고.. 많이 사용하는 스펙을 미리 정의 해놓고 사용하는 등.. 유용할 것 같다.




© 2019. by jaeuk