데이터 조회
findAll
모든 데이터를 조회
SshApplicationTests 수정
package com.myspringboot.ssh;
import static org.junit.jupiter.api.Assertions.assertEquals; // 추가
import java.time.LocalDateTime;
import java.util.List; // 추가
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest // @SpringBootTest 애너테이션은 SbbApplicationTests 클래스가 스프링부트 테스트 클래스임을 의미
class SshApplicationTests {
@Autowired // @Autowired 애너테이션은 스프링의 DI 기능으로 questionRepository 객체를 스프링이 자동으로 생성
private QuestionRepository questionRepository;
@Test
void testJpa() {
List<Question> all = this.questionRepository.findAll();
assertEquals(2, all.size());
Question q = all.get(0);
assertEquals("스프링부트가 무엇인가요?", q.getSubject());
}
}
assertEquals
assertEquals(기대값, 실제값)와 같이 사용하고 기대값과 실제값이 동일한지를 조사한다.
만약 기대값과 실제값이 동일하지 않다면 테스트는 실패로 처리된다.
우리는 총 2건의 데이터를 저장했기 때문에 데이터의 사이즈는 2가 되어야 한다.
데이터 사이즈가 2인지 확인하기 위해 JUnit의 assertEquals 메서드를 사용했다.
추가로 첫번째 데이터의 제목이 "스프링부트가 무엇인가요?"와 일치하는지도 테스트했다.
테스트를 위해서는 로컬 서버를 중지하고 다시한번 [Run -> Run As -> JUnit Test]을 실행하면 된다.
테스트가 통과 했다면 다음과 같은 화면이 뜬다.
findById
엔티티의 id값으로 조회
엔티티의 id 값으로 데이터를 조회하기 위해서는 리포지터리의 findById 메서드를 사용한다.
SshApplicationTests 수정
package com.myspringboot.ssh;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Optional; // 추가
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest // @SpringBootTest 애너테이션은 SbbApplicationTests 클래스가 스프링부트 테스트 클래스임을 의미
class SshApplicationTests {
@Autowired // @Autowired 애너테이션은 스프링의 DI 기능으로 questionRepository 객체를 스프링이 자동으로 생성
private QuestionRepository questionRepository;
@Test
void testJpa() {
Optional<Question> oq = this.questionRepository.findById(1);
if(oq.isPresent()) {
Question q = oq.get();
assertEquals("스프링부트가 무엇인가요?", q.getSubject());
}
}
}
findById의 리턴 타입은 Question이 아닌 Optional임에 주의 !!
Optional은 null 처리를 유연하게 처리하기 위해 사용하는 클래스로 위와 같이 isPresent로 null이 아닌지를 확인한 후에 get 으로 실제 Question 객체 값을 얻어야 한다.
마찬가지로 테스트에 성공한다면 다음과 같은 화면이 뜰 것이다.
findBySubject
특정 컬럼(subject)로 조회
Question 리포지터리는 findBySubject와 같은 메서드를 기본적으로 제공하지는 않기 떄문에 Question 엔티티의 subject 값으로 데이터를 조회하기 위해서는 QuestionRepository 인터페이스를 다음과 같이 변경해야 한다.
QuestionRepository
package com.myspringboot.ssh;
import org.springframework.data.jpa.repository.JpaRepository;
public interface QuestionRepository extends JpaRepository<Question, Integer>{
Question findBySubject(String subject); // 추가
}
SshApplicationTests 수정
package com.myspringboot.ssh;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest // @SpringBootTest 애너테이션은 SbbApplicationTests 클래스가 스프링부트 테스트 클래스임을 의미
class SshApplicationTests {
@Autowired // @Autowired 애너테이션은 스프링의 DI 기능으로 questionRepository 객체를 스프링이 자동으로 생성
private QuestionRepository questionRepository;
@Test
void testJpa() {
Question q = this.questionRepository.findBySubject("스프링부트가 무엇인가요?");
assertEquals(1, q.getId());
}
}
테스트를 실행해보면 잘 통과될 것이다.
인터페이스에 findBySubject 라는 메서드를 선언만 하고 구현은 하지 않았는데 어떻게 실행이 되는건가?
JpaRepository를 상속한 QuestionRepository 객체가 생성될때 벌어진다.
(DI에 의해 스프링이 자동으로 QuestionRepository 객체를 생성한다. 이 때 프록시 패턴이 사용된다고 한다.)
리포지터리 객체의 메서드가 실행될때 JPA가 해당 메서드명을 분석하여 쿼리를 만들고 실행한다.
findBy + 엔티티의 속성명(예:findBySubject)과 같은 리포지터리 메서드를 작성하면 해당 속성의 값으로 데이터를 조회할수 있다.
findBySubject 메서드를 호출할때 실제 어떤 쿼리가 실행되는지 살펴보자. 실행되는 쿼리를 로그에서 보려면 application.properties 파일을 다음과 같이 수정해야 한다.
application.properties
# DATABASE
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.datasource.url=jdbc:h2:~/local
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
# JPA
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update
#Hibernate이 DB에 날리는 모든 쿼리(DDL, DML) 표출
spring.jpa.properties.hibernate.show_sql=true
#쿼리 들여쓰기 등의 포맷에 맞춰 표출
spring.jpa.properties.hibernate.format_sql=true
#주석 표시하기
spring.jpa.properties.hibernate.use_sql_comments=true
#파라미터 값 표출
logging.level.org.hibernate.type.descriptor.sql=trace
수정이 완료된 후 다시 테스트코드를 실행해 보면 콘솔창에 아래와 같이 쿼리가 보여지게 된다.
findBySubjectAndContent
두 개의 속성을 And 조건으로 조회
QuestionRepository
package com.myspringboot.ssh;
import org.springframework.data.jpa.repository.JpaRepository;
public interface QuestionRepository extends JpaRepository<Question, Integer>{
Question findBySubject(String subject);
Question findBySubjectAndContent(String subject, String content); // 추가
}
SbbApplicationTests 수정
package com.myspringboot.ssh;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest // @SpringBootTest 애너테이션은 SbbApplicationTests 클래스가 스프링부트 테스트 클래스임을 의미
class SshApplicationTests {
@Autowired // @Autowired 애너테이션은 스프링의 DI 기능으로 questionRepository 객체를 스프링이 자동으로 생성
private QuestionRepository questionRepository;
@Test
void testJpa() {
Question q = this.questionRepository.findBySubjectAndContent(
"스프링부트가 무엇인가요?", "스프링부트에 대해서 알고 싶습니다.");
assertEquals(1, q.getId());
}
}
실행결과
리포지터리의 메서드명의 조합 예시
항목 | 예제 | 설명 |
And | findBySubjectAndContent(String subject, String content) | 여러 컬럼을 and 로 검색 |
Or | findBySubjectOrContent(String subject, String content) | 여러 컬럼을 or 로 검색 |
Between | findByCreateDateBetween(LocalDateTime fromDate, LocalDateTime toDate) | 컬럼을 between으로 검색 |
LessThan | findByIdLessThan(Integer id) | 작은 항목 검색 |
GreaterThanEqual | findByIdGraterThanEqual(Integer id) | 크거나 같은 항목 검색 |
Like | findBySubjectLike(String subject) | like 검색 |
In | findBySubjectIn(String[] subjects) | 여러 값중에 하나인 항목 검색 |
OrderBy | findBySubjectOrderByCreateDateAsc(String subject) | 검색 결과를 정렬하여 전달 |
단, 응답 결과가 여러건인 경우에는 리포지터리 메서드의 리턴 타입을 Question이 아닌 List<Question> 으로 해야 한다.
findBySubjectLike
특정 문자열이 포함되어 있는 데이터를 조회
QuestionRepository
package com.myspringboot.ssh;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
public interface QuestionRepository extends JpaRepository<Question, Integer>{
Question findBySubject(String subject);
Question findBySubjectAndContent(String subject, String content);
List<Question> findBySubjectLike(String subject);
}
SbbApplicationTests 수정
package com.myspringboot.ssh;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest // @SpringBootTest 애너테이션은 SbbApplicationTests 클래스가 스프링부트 테스트 클래스임을 의미
class SshApplicationTests {
@Autowired // @Autowired 애너테이션은 스프링의 DI 기능으로 questionRepository 객체를 스프링이 자동으로 생성
private QuestionRepository questionRepository;
@Test
void testJpa() {
List<Question> qList = this.questionRepository.findBySubjectLike("스프링%");
Question q = qList.get(0);
assertEquals("스프링부트가 무엇인가요?", q.getSubject());
}
}
Like 검색을 위해서는 findBySubjectLike 메서드의 입력 문자열로 "스프링%"와 같이 "%"를 적어주어야 한다.
실행결과
데이터 수정
SbbApplicationTests 수정
package com.myspringboot.ssh;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest // @SpringBootTest 애너테이션은 SbbApplicationTests 클래스가 스프링부트 테스트 클래스임을 의미
class SshApplicationTests {
@Autowired // @Autowired 애너테이션은 스프링의 DI 기능으로 questionRepository 객체를 스프링이 자동으로 생성
private QuestionRepository questionRepository;
@Test
void testJpa() {
Optional<Question> oq = this.questionRepository.findById(1);
assertTrue(oq.isPresent()); // assertTrue(값)은 값이 true인지를 테스트한다.
Question q = oq.get();
q.setSubject("Spring Boot 가 무엇인가요?");
this.questionRepository.save(q);
}
}
변경된 Question 데이터를 저장하기 위해서는 this.questionRepository.save(q) 처럼 리포지터리의 save 메서드를 사용
실행결과
데이터 삭제하기
SbbApplicationTests 수정
package com.myspringboot.ssh;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest // @SpringBootTest 애너테이션은 SbbApplicationTests 클래스가 스프링부트 테스트 클래스임을 의미
class SshApplicationTests {
@Autowired // @Autowired 애너테이션은 스프링의 DI 기능으로 questionRepository 객체를 스프링이 자동으로 생성
private QuestionRepository questionRepository;
@Test
void testJpa() {
assertEquals(2, this.questionRepository.count());
Optional<Question> oq = this.questionRepository.findById(1);
assertTrue(oq.isPresent());
Question q = oq.get();
this.questionRepository.delete(q);
assertEquals(1, this.questionRepository.count());
}
}
리포지터리의 count() 메서드는 해당 리포지터리의 총 데이터건수를 리턴
Question 리포지터리의 delete 메서드를 사용하여 데이터를 삭제했다.
삭제하기 전에는 데이터 건수가 2, 삭제한 후에는 데이터 건수가 1인지를 테스트했다
실행결과
참조 및 출처 : 점프 투 스프링부트 - https://wikidocs.net/160890
'Backend > Spring Boot' 카테고리의 다른 글
[Spring Boot] 도메인 나누기 (0) | 2022.08.10 |
---|---|
[Spring Boot] JPA Repository (3/3) (0) | 2022.08.10 |
[Spring Boot] JPA Repository (1/3) (0) | 2022.08.05 |
[Spring Boot] Entity (엔티티) (0) | 2022.08.04 |
[Spring Boot] JPA (0) | 2022.08.04 |