[Spring JPA #25] Spring JPA Specification

2021. 3. 26. 01:41 Spring Data/Spring Data JPA

 

| Spring JPA Specification

 

Spring JPA Specification은 Spring JPA에서 제공하는 검색 조건을 메서드 형태로 추상화하여 Repository 인터페이스에서 해당 검색 조건을 조합하고 쿼리하기 쉽게 할 수 있는 기능입니다.

 

| Spring JPA Specification 예제

 

프로젝트 구조

+---src
|   +---main
|   |   +---java
|   |   |   \---com
|   |   |       \---tutorial
|   |   |           \---springboot
|   |   |                   Application.java
|   |   |                   Comment.java
|   |   |                   CommentRepository.java
|   |   |                   CommentSpecs.java
|   |   |
|   |   \---resources
|   |       |   application.properties
|   |       |
|   |       +---static
|   |       \---templates
|   \---test
|       \---java
|           \---com
|               \---tutorial
|                   \---springboot
|                           ApplicationTests.java

 

의존성 관리

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-jpamodelgen</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

 

설정 관리

 

Intllij 기준 Setting -> Compiler -> Annotation Processor에 다음과 같이 설정합니다.

 

 

설정후 mvn compile 명령어로 아래와 같은 도메인 클래스를 생성해야 합니다.

@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(Comment.class)
public abstract class Comment_ {

   public static volatile SingularAttribute<Comment, Post> post;
   public static volatile SingularAttribute<Comment, String> comment;
   public static volatile SingularAttribute<Comment, Boolean> best;
   public static volatile SingularAttribute<Comment, Long> id;
   public static volatile SingularAttribute<Comment, Integer> up;
   public static volatile SingularAttribute<Comment, Integer> down;

   public static final String POST = "post";
   public static final String COMMENT = "comment";
   public static final String BEST = "best";
   public static final String ID = "id";
   public static final String UP = "up";
   public static final String DOWN = "down";

}

 

소스 코드

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
@Entity
@Data
public class Comment {

    @Id
    @GeneratedValue
    private Long id;

    private String comment;

    @ManyToOne
    private Post post;

    private int up;

    private int down;

    private boolean best;
}
public interface CommentRepository extends JpaRepository<Comment, Long>, JpaSpecificationExecutor<Comment> {
}
  • JpaSpecifiactionExecutor를 추가하여 Specification을 Repository의 메서드에서 사용할 수 있게 명시해야합니다.
public class CommentSpecs {

    public static Specification<Comment> isBest() {
        return new Specification<Comment>() {
            @Override
            public Predicate toPredicate(Root<Comment> root,
                                         CriteriaQuery<?> query,
                                         CriteriaBuilder builder) {
                return builder.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) {
                return criteriaBuilder.greaterThan(root.get(Comment_.up), 10);
            }
        };
    }
}

 

  • Comment 엔티티의 스펙을 정의합니다. Predicate 인터페이스를 반환하여 이 조건이 맞는지 확인하는 절차를 거치게 됩니다. CriteriaBuilder 클래스를 통하여 조건문을 정의할 수 있고 정의된 스펙들은 조합하여 쓸 수 있습니다.

 

테스트 코드

@RunWith(SpringRunner.class)
@DataJpaTest
public class ApplicationTests {

    @Autowired
    CommentRepository commentRepository;

    @Test
    public void specs() {
        commentRepository.findAll(CommentSpecs.isBest());
    }
}

 

https://www.inflearn.com/course/스프링-데이터-jpa



출처: https://engkimbs.tistory.com/837?category=772527 [새로비]