JPA로 원하는 매개변수로 findBy 메서드 생성하기
최근 "스타트 스프링부트" 라는 책으로 공부하는게 기본환경이 JPA를 활용하기 때문에 JPA에서 findBy를 이용해 쿼리 메소드를 작성하고 조회 조건처리 및 like 구문 처리 까지 정리하는 포스팅을 목표로 한다.
SQL문에서 특정한 칼럼의 값을 조회할 때는 쿼리 메서드의 이름을 findBy로 시작하는 방식을 이용한다.
Collection<T> findBy + 속성 이름(속성 타입)
예를들어, '게시물에서 user00이라는 작성자의 모든 데이터를 조회한다'는 기능을 BoardRepository에 추가하면 다음과 같이 코드를 작성한다.
package org.zerock.persistence;
import java.util.Collection;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import org.zerock.domain.Board;
public interface BoardRepository extends CrudRepository<Board, Long>{
public Collection<Board> findByWriter(String writer);
}
findBy...로 시작하는 쿼리 메서드는 지정하는 속성의 값에 따라 파라미터의 타입이 결정된다. Board 클래스에서 writer 속성의 값이 문자열이기 때문에 파라미터 타입은 String으로 지정했다.
📌 Test Case 추가
findBy.. 로 시작하는 쿼리 메서드의 리턴 타입은 Collection으로 설계하면 되기 때문에 forEach 구문을 이용해서 데이터를 출력하면 다음과 같은 형태가 된다.
package org.zerock;
import java.util.Collection;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.zerock.domain.Board;
import org.zerock.persistence.BoardRepository;
@RunWith(SpringRunner.class)
@SpringBootTest
class Boot03ApplicationTests {
@Autowired
private BoardRepository repo;
@Test
public void testByWriter() {
Collection<Board> results = repo.findByWriter("user00");
results.forEach(
board -> System.out.println(board)
);
}
}
테스트 코드를 실행하면 다음과 같이 where문 뒤에 writer 칼럼을 검색하는 코드가 추가되는 결과화면을 볼 수 있다.
// 실행 결과 - SQL에 where 조건이 추가된 것을 확인
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_.writer=?
Board(bno=10, title=제목..10, writer=user00, content=내용....10 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=20, title=제목..20, writer=user00, content=내용....20 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=30, title=제목..30, writer=user00, content=내용....30 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=40, title=제목..40, writer=user00, content=내용....40 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=50, title=제목..50, writer=user00, content=내용....50 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=60, title=제목..60, writer=user00, content=내용....60 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=70, title=제목..70, writer=user00, content=내용....70 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=80, title=제목..80, writer=user00, content=내용....80 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=90, title=제목..90, writer=user00, content=내용....90 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=100, title=제목..100, writer=user00, content=내용....100 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=110, title=제목..110, writer=user00, content=내용....110 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=120, title=제목..120, writer=user00, content=내용....120 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=130, title=제목..130, writer=user00, content=내용....130 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=140, title=제목..140, writer=user00, content=내용....140 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=150, title=제목..150, writer=user00, content=내용....150 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=160, title=제목..160, writer=user00, content=내용....160 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=170, title=제목..170, writer=user00, content=내용....170 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=180, title=제목..180, writer=user00, content=내용....180 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=190, title=제목..190, writer=user00, content=내용....190 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=200, title=제목..200, writer=user00, content=내용....200 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
📌 like 구문 처리
findBy와 더불어 가장 많이 사용하는 구문은 like 구문이다. like에 대한 처리는
- 단순한 like
- 키워드+'%'
- '%'+키워드
- '%'+키워드+'%'
like구문 쿼리작성을 자주 하셨던 분들은 익숙하겠지만 like구문을 사용할 때 위와 같이 4가지 형태를 사용한다.
이 4가지 형태를 쿼리 메서드로 정리해보면 아래와 같다.
형태 | 쿼리 메서드 |
단순 like | Like |
키워드 + '%' | StartingWith |
'%' + 키워드 | EndingWith |
'%' + 키워드 + '%' | Containing |
예를 들어, 게시물에서 작성자 이름에 '05'라는 문자가 들어있는 게시글을 검색하고 싶다면 BoardRepository에 다음과 같은 쿼리 메서드를 작성한다.
BoardRepository.java
package org.zerock.persistence;
import java.util.Collection;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import org.zerock.domain.Board;
public interface BoardRepository extends CrudRepository<Board, Long>{
// ...중간 생략...
// 작성자에 대한 like % 키워드 %
public Collection<Board> findByWriterContaining(String writer);
}
ApplicationTests.java
package org.zerock;
import java.util.Collection;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.zerock.domain.Board;
import org.zerock.persistence.BoardRepository;
@RunWith(SpringRunner.class)
@SpringBootTest
class Boot03ApplicationTests {
@Autowired
private BoardRepository repo;
@Test
public void testByWriterContaining() {
Collection<Board> results = repo.findByWriterContaining("05");
results.forEach(board -> System.out.println(board));
}
}
console(결과)
// 실행결과 - SQL에 like 처리가 되는 것을 확인
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_.writer like ? escape ?
Board(bno=5, title=제목..5, writer=user05, content=내용....5 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=15, title=제목..15, writer=user05, content=내용....15 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=25, title=제목..25, writer=user05, content=내용....25 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=35, title=제목..35, writer=user05, content=내용....35 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=45, title=제목..45, writer=user05, content=내용....45 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=55, title=제목..55, writer=user05, content=내용....55 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=65, title=제목..65, writer=user05, content=내용....65 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=75, title=제목..75, writer=user05, content=내용....75 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=85, title=제목..85, writer=user05, content=내용....85 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=95, title=제목..95, writer=user05, content=내용....95 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=105, title=제목..105, writer=user05, content=내용....105 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=115, title=제목..115, writer=user05, content=내용....115 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=125, title=제목..125, writer=user05, content=내용....125 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=135, title=제목..135, writer=user05, content=내용....135 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=145, title=제목..145, writer=user05, content=내용....145 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=155, title=제목..155, writer=user05, content=내용....155 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=165, title=제목..165, writer=user05, content=내용....165 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=175, title=제목..175, writer=user05, content=내용....175 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=185, title=제목..185, writer=user05, content=내용....185 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
Board(bno=195, title=제목..195, writer=user05, content=내용....195 채우기, regdate=2022-02-02 18:43:39.0, updatedate=2022-02-02 18:43:39.0)
'Programming > Spring' 카테고리의 다른 글
[Spring] MVC1, MVC2 개념 및 차이점 / Spring MVC 동작과정 (1) | 2022.07.17 |
---|---|
[Spring] Mybatis - foreach 사용법 및 예제 / 동적 반복 sql 처리 (0) | 2022.06.26 |
[Spring MVC] Dispatcher Servlet 이란? -(FrontController패턴 포함) (2) | 2021.06.15 |
[Spring] RestController, ResponseEntity란? (Controller와 RestController의 차이점 포함) (0) | 2021.05.24 |
[Spring] Ioc 컨테이너 - DL(Dependency Lookup) 과 DI(Dependency Injection) (2) | 2021.05.19 |