1) 쿼리 메서드
쿼리 메서드
- 특정 패턴에 맞게 메서드 이름을 작성하면 이를 파싱해서 그에 맞는 쿼리를 실행 해준다.
쿼리 패턴
- Query - 엔티티를 조회하는 데 사용 되는 메서드는 find..By, read..By, get..By, query..By, stream..By, search..By 형태로 이름 짓는다.
- Count - 엔티티의 개수를 세는 데 사용되는 메서드는 count..By 형태로 이름 짓는다.
- Exists - 엔티티의 존재 여부를 확인하는 데 사용되는 메서드는 exists..By 형태로 이름 짓는다.
- Delete - 엔티티를 삭제할 때 사용되는 메서드는 delete..By, remove..By 형태로 이름 짓는다.
1-1) 쿼리 메서드 예제
- 소스 코드 : /ch03/custom-query-method
Repository 인터페이스에 쿼리 메서드를 정의한다.
@Repository
public interface CourseRepository extends CrudRepository<Course, Long> {
Iterable<Course> findAllByCategory(String category);
Iterable<Course> findAllByCategoryOrderByName(String category);
boolean existsByName(String name);
long countByCategory(String category);
Iterable<Course> findByNameOrCategory(String name, String category);
Iterable<Course> findByNameStartsWith(String name);
Stream<Course> streamAllByCategory(String category);
}
2) PagingAndSortingRepository를 활용한 페이징 및 정렬
페이징(Pagination)
- 많은 양의 데이터를 여러 페이지로 잘게 나눠 조회하는 기법
PagingAndSortingRepository
- 페이지 단위로 데이터를 자르고 정렬할 수 있는 인터페이스
- CrudRepository를 상속받을므로 CRUD 연산을 수행할 수 있다.
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends Repository<T, ID> {
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
2-1) PagingAndSortingRepository 예제
PagingAndSortingRepository 확장
@Repository
public interface CourseRepository extends PagingAndSortingRepository<Course, Long> {
}
페이징 예제
@Test
public void givenDataAvailableWhenLoadFirstPageThenGetFiveRecords() {
Pageable pageable = PageRequest.of(0,3);
assertThat(courseRepository.findAll(pageable)).hasSize(3);
assertThat(pageable.getPageNumber()).isEqualTo(0);
Pageable nextPageable = pageable.next();
assertThat(courseRepository.findAll(nextPageable)).hasSize(1);
assertThat(nextPageable.getPageNumber()).isEqualTo(1);
}
- Pageable 은 요청된 페이지와 페이지당 데이터 수를 포함한다.
- PageRequest.of(페이지 번호, 페이지당 데이터수)를 통해 지정할 수 있다.
- findAll()에 pageable을 인자로 전달하여 페이지를 조회한다.
- Pageaable의 next() 는 다음 페이지를 요청하는 Pageable 객체를 반환한다.
정렬 예제
Pageable pageable = PageRequest.of(0, 5, Sort.Order.asc("Name"));
- Sort 객체를 메서드에 전달하여 정렬을 할 수 있다.
3) @NamedQuery를 사용하는 쿼리
직접 쿼리문을 지정해줘야할 필요가 있을 때 사용한다.
- 세밀하게 최적화된 쿼리가 이미 있고 특정 데이터베이스에 특화된 기능을 사용해야 하는 경우
- 두 개 이상의 테이블을 조인해서 데이터를 조회해야 하는 경우
NamedQuery
- 비즈니스 엔티티와 연계돼 있는 미리 정의된 쿼리
- JPQL(Jakarta Persistence Query Language)를 사용해서 정의한다.
- 엔티티 클래스 또는 엔티티 클래스의 수퍼클래스에 정의할 수 있다.
NamedQuery 정의 방법
- @NamedQuery 애너테이션을 엔티티 클래스에 붙인다.
- name(필수), query(필수), lockMode, hinst 속성을 가지고 있다.
3-1) NamedQuery 예제
- 소스 코드 : /ch03/named-query-method
Course 클래스에 @NamedQuery 애너테이션을 추가한다.
@Entity
@Table(name = "COURSES")
@NamedQuery(name = "Course.findAllByCategoryAndRating",
query = "select c from Course c where c.category=?1 and c.rating=?2")
public class Course {
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "CATEGORY")
private String category;
@Column(name = "RATING")
private int rating;
// 생략
}
- 여러 개의 @NamedQuery를 붙이려면 @NamedQueries 를 사용한다.
@NamedQueries({
@NamedQuery(name = "Course.findAllByCategoryAndRating",
query = "select c from Course c where c.category=?1 and c.rating=?2"),
@NamedQuery(name = "Course.findAllByCategory",
query = "select c from Course c where c.category=?1")
})
@NamedQuery 애너테이션에 정의한 메서드를 Repository 인터페이스에 추가
@Repository
public interface CourseRepository extends CrudRepository<Course, Long> {
Iterable<Course> findAllByCategoryAndRating(String category, int rating);
}
책
'실전 스프링부트' 카테고리의 다른 글
[ch05-1] 스프링 시큐리티 소개 (0) | 2024.03.19 |
---|---|
[ch03-5] @Query로 쿼리문 지정 (0) | 2024.03.12 |
[ch03-3] CrudRepository 인터페이스 이해 (0) | 2024.03.11 |
[ch03-2] 스프링 부트 어플리케이션 데이터베이스 연동 설정(Mysql) (0) | 2024.03.11 |
[ch03-1] 스프링 데이터 소개 (0) | 2024.03.11 |