2021. 10. 6. 16:05ㆍJAVA/Spring
이전글
https://yonghwankim-dev.tistory.com/135
본 글은 스타트 스프링 부트 도서의 내용을 복습하기 위해 작성된 글입니다.
개요
@Query 애노테이션을 활용하여 제목 및 내용에 대한 검색 처리를 수행하고 Paging 처리/정렬을 같이 수행할 수 있도록 실습합니다.
- 쿼리 메소드라는 메소드의 이름만으로 원하는 SQL을 실행하는 방법
- @Query를 이용한 좀 더 구체화된 JPQL 처리 (현재)
- 페이징과 정렬에 대한 처리
- Querydsl을 이용한 동적 쿼리
1. 단순 게시물의 처리를 위한 @Query 작성
1.1 제목에 대한 검색 처리
org.zerock.persistence.BoardRepository
public interface BoardRepository extends CrudRepository<Board, Long>{
// b.bno > 0 조건으로 인해서 탐색 성능 높힘
// 쿼리문에서 ?은 JDBC의 PreparedStatment 역할
// LIKE 문에서 1은 첫번재 파라미터라는 의미, title 문자열이 LIKE문에 삽입됨
@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);
}
@Query에는 JPQL(객체 쿼리)을 이용합니다. JPQL은 JPA에서 사용하는 Query Language입니다. SQL과 유사한 구문들로 구성되고, JPA의 구현체에서 이를 해석해서 실행합니다.
JPQL의 가장 기본적인 형태는 테이블(tbl_boards) 대신에 엔티티(Board) 타입을 이용한다는 것과 칼럼명 대신에 엔티티의 속성을 이용하는 것입니다.
org.zerock.Boot03ApplicationTests 일부, JPQL 테스트
@Test
void testByTitle2() {
// 게시물 제목에 17이 포함되는 게시물 검색
repo.findByTitle("17").forEach(board->System.out.println(board));
}
1.2 내용에 대한 검색 처리 - @Param
내용에 대한 검색 처리 역시 제목에 대한 검색 처리와 동일한 방식으로 처리할 수 있습니다. @Query에는 @Param을 적용이 가능하여 적용할 수 있습니다.
org.zerock.persistence.BoardRepository
public interface BoardRepository extends CrudRepository<Board, Long>{
// 게시물의 내용 검색
// 내용에 대한 검색 처리 - @Param
// @Param("content")로 설정된 content 문자열이 @Query 애노테이션의 LIKE문 :content에 매핑 됨
@Query("SELECT b FROM Board b WHERE b.title LIKE %:content% AND b.bno > 0 ORDER BY b.bno DESC")
public List<Board> findByContent(@Param("content") String content);
}
위의 작성된 코드를 보면 기존의 검색 처리 결과와 달리 '%:content%'와 같이 처리되는 것을 볼 수 있습니다. 파라미터에서는 @Param이라는 어노테이션을 이용하는 것을 볼 수 있습니다. @Param은 org.springframework.data.repository.query.Param 클래스를 이용합니다. 덕분에 여러 개의 파라미터를 전달할 때 이름을 이용해 쉽게 구분해서 전달이 가능합니다.
org.zerock.Boot03ApplicationTests 일부
@Test
void testByContent2() {
// 게시물 내용에 17이 포함되는 게시물 검색
repo.findByContent("17").forEach(board->System.out.println(board));
}
2. @Query의 활용
@Query 애노테이션을 활용하여 얻을 수 있는 장점
- 리턴 값이 반드시 엔티티 타입이 아니라 필요한 몇 개의 칼럼 값들만 추출 가능
- nativeQuery 속성을 지정해서 데이터베이스에 사용하는 SQL을 그대로 사용할 수 있음
- Repository에 지정된 엔티티 타입 뿐 아니라 필요한 엔티티 타입을 다양하게 사용할 수 있음
2.1 필요한 칼럼만 추출하는 경우
@Query를 이용하면 'select'로 시작하는 JPQL 구문을 작성하는데, 이때 필요한 칼럼만을 추출할 수 있습니다.
아래 예제는 Board 엔티티 타입에서 content 칼럼의 내용을 제외한 칼럼을 가져오는 예제입니다.
org.zerock.persistence.BoardRepository
public interface BoardRepository extends CrudRepository<Board, Long>{
// 게시물의 제목 검색
// 필요한 컬럼만 추출하는 경우 사용
@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);
}
org.zerock.Boot03ApplicationTests 일부
@Test
void testByTitle17() {
// 게시물의 제목이 17이 포함되는 게시물 검색
// 필요한 컬럼만 추출하는 테스트, content 칼럼의 내용을 제외하고 검색
repo.findByTitle2("17").forEach(arr->System.out.println(Arrays.toString(arr)));
}
여러 칼럼을 특정한 경우 리턴 타입은 엔티티 타입이 아니라 Object[]의 리스트 형태입니다. 때문에 Object[]로 반환되기 때문에 배열을 출력해야 합니다.
2.2 nativeQuery 사용
@Query는 말 그대로 데이터베이스에 종속적인 SQL문을 그대로 사용할 수 있기 때문에 복잡한 쿼리 작성시 유용하게 사용할 수 있습니다. 다만, 이 경우 데이터베이스 언어에 종속적이기 때문에 주의해야 합니다.
@Query 애노테이션에 nativeQuery 속성을 'true'라고 지정하면 메소드 실행 시 @Query의 value값을 그대로 실행하게 됩니다.
org.zerock.persistence.BoardRepository
public interface BoardRepository extends CrudRepository<Board, Long>{
// 게시물의 제목 검색
// nativeQuery 사용
// nativeQuery 사용시(nativeQuery=true) @Query의 value값을 그대로 실행함
@Query(value = "select bno, title, writer from tbl_boards where title like CONCAT('%',?1,'%') "
+ " and bno>0 order by bno desc",nativeQuery = true)
public List<Object[]> findByTitle3(String title);
}
org.zerock.Boot03ApplicationTests 일부
@Test
void testByTitle20() {
// 게시물의 제목이 20이 포함되는 게시물 검색
// nativeQuery 사용 테스트
repo.findByTitle3("20").forEach(arr->System.out.println(Arrays.toString(arr)));
}
3. @Query와 Paging 처리/정렬
@Query를 이용하더라도 페이징 처리를 하는 Pageable 인터페이스는 그대로 활용이 가능합니다. 만일 메서드의 파라미터에 Pageable 타입을 사용하게 되면 '@Query로 작성한 내용 + 페이징 처리'의 형태가 됩니다.
org.zerock.persistence.BoardRepository
public interface BoardRepository extends CrudRepository<Board, Long>{
// 게시물 전체 검색
// @Query와 Paging 처리/정렬
// @Query로 작성한 내용 + 페이징 처리, 같이 수행 가능
@Query("SELECT b FROM Board b WHERE b.bno>0 ORDER BY b.bno DESC")
public List<Board> findBypage(Pageable pageable);
}
org.zerock.Boot03ApplicationTests 일부
@Test
void testByPaging() {
// 한페이지에 10건의 데이터 페이징 처리하여 전체 게시물 검색
Pageable paging = PageRequest.of(0, 10);
repo.findBypage(paging).forEach(board->System.out.println(board));
}
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_.bno>0 order by board0_.bno DESC limit ?
Board(bno=408, title=제목.. 200, writer=user00, content=내용...200 채우기, regdate=2021-10-04 13:11:13.0, updatedate=2021-10-04 13:11:13.0)
Board(bno=407, title=제목.. 199, writer=user09, content=내용...199 채우기, regdate=2021-10-04 13:11:13.0, updatedate=2021-10-04 13:11:13.0)
Board(bno=406, title=제목.. 198, writer=user08, content=내용...198 채우기, regdate=2021-10-04 13:11:13.0, updatedate=2021-10-04 13:11:13.0)
Board(bno=405, title=제목.. 197, writer=user07, content=내용...197 채우기, regdate=2021-10-04 13:11:13.0, updatedate=2021-10-04 13:11:13.0)
Board(bno=404, title=제목.. 196, writer=user06, content=내용...196 채우기, regdate=2021-10-04 13:11:13.0, updatedate=2021-10-04 13:11:13.0)
Board(bno=403, title=제목.. 195, writer=user05, content=내용...195 채우기, regdate=2021-10-04 13:11:13.0, updatedate=2021-10-04 13:11:13.0)
Board(bno=402, title=제목.. 194, writer=user04, content=내용...194 채우기, regdate=2021-10-04 13:11:13.0, updatedate=2021-10-04 13:11:13.0)
Board(bno=401, title=제목.. 193, writer=user03, content=내용...193 채우기, regdate=2021-10-04 13:11:13.0, updatedate=2021-10-04 13:11:13.0)
Board(bno=400, title=제목.. 192, writer=user02, content=내용...192 채우기, regdate=2021-10-04 13:11:13.0, updatedate=2021-10-04 13:11:13.0)
Board(bno=399, title=제목.. 191, writer=user01, content=내용...191 채우기, regdate=2021-10-04 13:11:13.0, updatedate=2021-10-04 13:11:13.0)
References
스타트 스프링 부트, 구멍가게 코딩단 저
'JAVA > Spring' 카테고리의 다른 글
SpringBoot #5 다양한 연관관계 처리 #1 연관관계 처리 순서와 사전 설계 (0) | 2021.10.11 |
---|---|
Spring Data JPA #4 단순 게시글 처리 #4 Querydsl을 이용한 동적 SQL의 처리 (0) | 2021.10.06 |
Spring Data JPA #4 단순 게시글 처리 #2 쿼리 메서드의 페이징 처리와 정렬 (0) | 2021.10.06 |
Spring Data JPA #4 단순 게시글 처리 #1 쿼리 메서드 사용 (0) | 2021.10.06 |
Spring Data JPA #3 Spring Data JPA를 위한 프로젝트 생성 #2 (0) | 2021.10.01 |