> For the complete documentation index, see [llms.txt](https://djunnni.gitbook.io/springboot/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://djunnni.gitbook.io/springboot/2019-09-05.md).

# 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를 하나씩 작성하고, 프로젝트를 실행하는 과정을 거치는 것이 좋다.
