데이터 조회

 

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임에 주의 !!

Optionalnull 처리를 유연하게 처리하기 위해 사용하는 클래스로 위와 같이 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

 

수정이 완료된 후 다시 테스트코드를 실행해 보면 콘솔창에 아래와 같이 쿼리가 보여지게 된다.

실행된 쿼리의 where 조건에 subject가 포함된 것을 확인할 수 있다.


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());
	} 

}

 

 

실행결과

subject, content 컬럼이 and 조건으로 where문에 사용


리포지터리의 메서드명의 조합 예시

 

항목 예제 설명
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 메서드를 사용

 

실행결과

update 문이 실행되었음을 확인할 수 있을 것이다.

 


데이터 삭제하기

 

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

+ Recent posts