Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 15486
- 퇴사 2
- 에라토스테네스의 체
- image crawling
- 다이나믹 프로그래밍
- 그르다 김가놈
- 이분 탐색
- 마스크 재고 확인
- meet in the middle
- 9328
- 공적 마스크
- 18249
- 부루트 포스
- 18113
- 18248
- 욱제가 풀어야 하는 문제
- 산업 스파이의 편지
- 마스크 5부제
- 18235
- 3671
- BOJ
- 깊이 우선 탐색
- 냅색문제
- 알고리즘
- 단어 수학
- 카드 놓기
- 9466
- 메일 전체 읽기
- 18114
- 18115
Archives
- Today
- Total
groti's blog
[Spring Boot ] JPA Specification 이용하여 쿼리 조건 다루기 본문
JPA를 사용할 때 쿼리 메서드를 통해 where 조건 추가할 수 있다.
예를 들어, Id로 검색할 경우 findById, Id와 name으로 검색하려면 findByIdAndName으로 쿼리 메서드를 만들 수 있다.
하지만 함께 검색할 검색의 조합이 다양해지면 만들어야 하는 쿼리 메서드도 많아진다.
이럴 때 Specification을 이용하면 원하는 조건을 상황에 맞게 선택하여 추가할 수 있다.
Todo 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;
}
JpaTodoRepository 인터페이스 만들고 JpaSpecificationExecutor 상속 받기
import com.leanne.edu.springboot.todo.model.Todo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
public interface JpaTodoRepository extends JpaRepository<Todo, Integer>, JpaSpecificationExecutor<Todo> {
}
List<T> findAll(@Nullable Specification<T> spec);
Specification을 인자로 받는 findAll 함수를 사용하기 위해서는 인터페이스에 JpaSpecificationExecutor를 상속받아야 한다.
TodoSpecification 클래스 만들고 쿼리 조건 함수로 추가하기
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.LocalDateTime;
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);
}
};
}
}
1) criteriaBuilder.equal(root.get("todoId"), todoId)
-> todo_id = ?
2) criteriaBuilder.like(root.get("contents"), "%" + contents + "%")
-> content like = ?
3) criteriaBuilder.between(root.get("createdDatetime"), startDatetime, endDatetime)
-> created_datetime between ? and ?
검색 조건에 맞게 쿼리 조건 추가하기
public List<Todo> searchTodoList(Long todoId, String contents, LocalDateTime startDatetime, LocalDateTime endDatetime) {
Specification<Todo> spec = Specification.where(TodoSpecification.equalTodoId(todoId));
if(contents != null) {
spec = spec.and(TodoSpecification.likeContents(contents));
}
if(startDatetime != null && endDatetime != null) {
spec = spec.and(TodoSpecification.betweenCreatedDatetime(startDatetime, endDatetime));
}
return jpaTodoRepository.findAll(spec);
}
함수 인자를 확인하여 포함된 검색 조건은 spec에 추가하고 그렇지 않은 조건은 spec에서 제외한다.
실행 결과 확인
검색조건이 정상적으로 추가된 것을 확인할 수 있다.
Comments