JPA Specification

전윤지·2021년 12월 14일
0

Spring

목록 보기
4/5

1. Specification이란?

  • 동적 쿼리를 사용하기 위한 JPA 라이브러리
    • 단순 JPA 메서드를 사용하면, findByIdAndName등으로 메서드 생성.
      검색할 객체의 조합이 다양해지면, 만들어야 하는 쿼리 메서드도 많아짐
      => 복잡 & 가독성 떨어짐.
  • 컴파일 시점에서 에러 확인 가능
  • JPA Criteria 객체 지원

2. Specification 사용

1) DTO 생성

@Entity
@Table(name = "TODO")
@NoArgsConstructor
@Data
public class Todo {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long todoId;

    private String contents;

    @Column(nullable = false)
    private LocalDateTime createdDatetime = LocalDateTime.now();

    private LocalDateTime updatedDatetime;

    @ColumnDefault(value="'N'")
    private String completeYn;
}

2) Repository 생성

  • JpaSpecificationExecutor< T >를 상속받는 repository를 생성함

// JpaSpecificationExecutor를 상속받는 Repository
public interface JpaTodoRepository extends JpaRepository<Todo, Integer>, JpaSpecificationExecutor<Todo> {
}
// JpaSpecificationExecutor 내부
public interface JpaSpecificationExecutor<T> {
    T findOne (Specification<T> spec);
    List<T> findAll (Specification<T> spec);
    Page<T> findAll (Specification<T> spec, Pageable pageable);
    List<T> findAll (Specification<T> spec, Sort sort);
    long count(Specification<T> spec);
}

3) Specification 객체 생성

  • toPredicate() 함수를 오버라이딩해서 사용
  • root.get("...")사용 시, "..."안에는 entity 속성의 이름을 사용해야 함

public class TodoSpecification {

    public static Specification<Todo> equalTodoId(Long todoId) {
        return new Specification<Todo>() {
            @Override
            public Predicate toPredicate(Root<Todo> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                // 1) equal
                return criteriaBuilder.equal(root.get("todoId"), todoId);
            }
        };
    }

    public static Specification<Todo> likeContents(String contents) {
        return new Specification<Todo>() {
            @Override
            public Predicate toPredicate(Root<Todo> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                // 2) like
                return criteriaBuilder.like(root.get("contents"), "%" + contents + "%");
            }
        };
    }

    public static Specification<Todo> betweenCreatedDatetime(LocalDateTime startDatetime, LocalDateTime endDatetime) {
        return new Specification<Todo>() {
            @Override
            public Predicate toPredicate(Root<Todo> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                // 3) between
                return criteriaBuilder.between(root.get("createdDatetime"), startDatetime, endDatetime);
            }
        };
    }
}
  • criteriaBuilder.equal(root.get("todoId"), todoId)
    : root.get("todoId") = todoId ?
  • criteriaBuilder.like(root.get("contents"), "%" + contents + "%")
    : root.get("contents") like contents ?
  • criteriaBuilder.between(root.get("createdDatetime"), startDatetime, endDatetime)
    : root.get("createdDatetime") between startDatetime and endDatetime ?


참고 블로그 : https://groti.tistory.com/49

0개의 댓글