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