3. Spring Data JPA 를 이용한 쿼리 연습
쿼리 메소드 리턴 타입
Page , Slice, List 같은 Collection 형태가 된다.
repository에 작성할때, 쿼리 예시
public List<Board> findBoardByTitle(String title);
find + { 찾고자 하는 클래스 } + By + { 무엇으로 찾을 지 } (type)
findBy를 통해 특정 칼럼을 처리하는 법
1.
Collection<T> findBy + 속성 이름(속성 타입)
ex)
public Collection<Board> findByWriter(String writer);
2.
@Test
public void testByWriter() {
Collection<Board> results = repo.findByWriter("user00");
reuslts.forEach(
board -> System.out.println(board)
);
}
Page import 에 해깔림이 있으시는 분
- Pageable = import org.springframework.data.domain.Pageable;
- PageRequest = import org.springframework.data.domain.PageRequest;
- Page = import org.springframework.data.domain.Page;
JPA Paging 이 필요할 때 사용하려면
ex)
public List<Board> findByBnoGreaterThanOrderByBnoDesc(Long bno,Pageable paging)
코드는 기존과 동일하지만, 파라미터에 Pageable이 적용되었고 Collection<> 에서 List<> 로 변경되었습니다.
Pageable 인터페이스가 적용되는 경우는 리턴타입이 Slice, Page, List 타입이다.
페이징에 가장 많이 사용되는 PageRequest
PageRequest는 SpringBoot 2.0으로 넘어오면서 PageRequest.of()를 사용하고 있다.
JPA 와 Spring MVC와 연동할 때 Page 타입을 쓰자.
Page 타입을 이용하면 Spring MVC와 연동할 때 상당한 편리함을 주는데 지금부터 알아보자.
public interface BoardRepository extends CrudRepository<Board,Long>{
public Page<Board> findByBnoGreaterThan(Long bno,Pageable paging);
}
ex) Test java case
@Test
public void testBnoPagingSort(){
//Spring boot 2.0
Pageable paging = PageRequest.of(0,10,Sort.Direction.ASC,"bno");
Page<Board> result = repo.findByBnoGreaterThan(0L,paging);
System.out.println(result.getSize());
System.out.println(result.getTotalPages());
System.out.println(result.getTotlalElements());
System.out.println(result.nextPageable());
List<Board> list = result.getContent();
list.forEach(board -> System.out.prinln(board));
}
위 코드를 실행하게 되면 아래처럼 결과가 나온다.
10
20
200
Page request [number:1, size 10, sort: bno: ASC]
Board(bno=1 ...) => //getContent를 통해 객체를 받아올수 있다.
@Query 이용법
왜? @Query 어노테이션을 사용할까?
PK(Primary Key)를 이용하여 Full table Scan을 하게 되면 모든 데이터에 대해 검색을 통해 처리되기 때문에 성능이 나쁠 수 있다는 견해가 있다. (하지만 병렬 처리가 효과적으로 처리되면 더 빠른 경우도 있음)
'where bno > 0 ' 과 같은 표현이 JPA 메소드에 표현하기에는 어색함 -> @query 를 사용하게 됨
@Query("Select b from board b where b.title like %?1% and b.bno > 0 order by b.bno desc")
public List<Board> findByTitle(String title);
%?1%을 살펴보면 '?'는 JDBC의 PreparedStatement와 동일 '?1'은 첫번째로 전달되는 파라미터를 의미한다.
실행결과 Query
Hibernate: select board0_.bno as bno1_0_, board0_.content as content2_0_, board0_.regdate as regdate3_0_, board0_.title as title4_0_, board0_.updatedate as updateda5_0_, board0_.writer as writer6_0_ from tbl_boards board0_ where (board0_.title like ?) and board0_.bno>0 order by board0_.bno desc
Query의 장점
리턴값이 반드시 엔티티 타입이 아니라 필요한 몇 개의 칼럼만 추출할 수 있다.
nativeQuery 속성을 지정해서 데이터베이스에 사용하는 SQL을 그대로 사용할 수 있다.
Repository에 지정된 엔티티 타입뿐아니라 필요한 엔티티 타입을 다양하게 사용할 수 있다.
Query Cost 란?
Query가 실행되는 데 걸리는 예상 수행시간
@Param 사용법
@Query("SELECT b FROM Board b where b.content like %:content% AND b.bno>0 order by b.bno desc")
public List<Board> findByContent(@Param("content") String content);
@Test
public void testByContent2() {
repo.findByContent("18").forEach(board->System.out.println(board));
}
필요한 칼럼만 추출하는 경우
특정 칼럼만 가져오고 싶다면 아래와 같은 방식으로 작성하면 된다.
@Query("select b.bno, b.title, b.writer, b.regdate"+" from Board b WHERE b.title like %?1% and b.bno>0 order by b.bno desc")
public List<Object[]> findByTitle2(String title);
@Test
public void testBytitle17() {
repo.findByTitle2("17").forEach(arr->System.out.println(Arrays.toString(arr)));
}
@Query 와 Paging 처리/정렬
@Query("select b from Board b WHERE b.bno > 0 order by b.bno desc")
public List<Board> findByPage(Pageable pageable);
@Test
public void testByPaging() {
Pageable pageable = PageRequest.of(0, 10);
repo.findByPage(pageable).forEach(board->System.out.println(board));
}
@Query를 이용할 때 주의할 점
@Query에 대한 해석은 프로젝트 로딩 시점에서 이루어진다. 따라서 @Query의 내용은 프로젝트가 시작되면서 검증되기 때문에 만일 @Query의 내용물이 잘못될 경우에는 프로젝트가 정상적으로 실행되지 않는다.
권고 : @Query를 하나씩 작성하고, 프로젝트를 실행하는 과정을 거치는 것이 좋다.
Last updated
Was this helpful?