[SpringBoot] 리포지터리 데이터베이스 관리 기본 기능

2024. 8. 27. 22:01자바 웹 개발/스프링부트

리포지터리란?

데이터를 관리하려면 데이터베이스와 연동하는 JPA 리포지터리가 필요하다. 리포지터리는 데이터베이스의 데이터를 저장, 조회, 수정, 삭제 등을 할 수 있도록 도와주는 인터페이스다. 리포지터리는 데이터를 관리하는 메서드를 제공한다. 

public interface QuestionRepository extends JpaRepository<Question, Integer> {
  Question findBySubject(String subject);
  Question findBySubjectAndContent(String subject, String content);
  List<Question> findBySubjectLike(String subject);
}
public interface AnswerRepository extends JpaRepository<Answer, Integer> {

}


리포지터리는 JpaRepository 인터페이스를 상속해야한다. JpaRepository 인터페이스는 CRUD 작업을 처리하는 메서드를 내장하고 있다. Question 엔티티의 기본키가 Integer임을 추가로 지정해야 한다. 

 

JUnit 설치하기 

JUnit은 테스터 코드를 위해 사용되는 프레임워크이다. 

build.gradle 파일에 다음 내용을 추가한다. 

testImplementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

 

 

테스트 실시하기

@SpringBootTest는 이 메서드가 테스트 메서드임을 알려준다. 이 클래스를 JUnit으로 실행하면 @Test가 붙은 testJpa 메서드가 실행된다. 

@Autowired는 스프링의 '의존성 주입'이라는 기능을 사용하여 QuestionRepository 객체를 자동으로 만들어 주입한다. 다만, 생성자를 통한 객체 주입 방식이 권장된다. 

@SpringBootTest
public class ApplicationTests {

  @Autowired
  private QuestionRepository questionRepository;

  @Test
  void testJpa(){
    Question q1 = new Question();
    q1.setSubject("sbb가 무엇인가요?");
    q1.setContent("sbb에 대해서 알고 싶습니다");
    q1.setCreateDate(LocalDateTime.now());
    this.questionRepository.save(q1);

    Question q2 = new Question();
    q2.setSubject("스프링 부트 모델 질문입니다");
    q2.setContent("id는 자동으로 생성되나요?");
    q2.setCreateDate(LocalDateTime.now());
    this.questionRepository.save(q2);
  }
}

 

findAll 

모든 데이터를 조회하는 메서드이다. SELECT * FROM QUESTION과 같은 결과를 얻을 수 있다. 

@SpringBootTest
class ApplicationTestsTest {

  @Autowired
  private QuestionRepository questionRepository;

  @Test
  void testJpa() {
    List<Question> all = this.questionRepository.findAll();
    assertEquals(2, all.size());

    Question q = all.get(0);
    assertEquals("sbb가 무엇인가요?", q.getSubject());
  }
}

assertEquals 메서드는 테스트에서 예상한 결과와 실제 결과가 동일한지를 확인하는 목적에서 사용한다. 동일하지 않다면 테스트는 실패 처리된다. 

 

findById

  @Test
  void testJpa() {
    Optional<Question> op = questionRepository.findById(1);
    if(op.isPresent()) {
      Question question = op.get();
      assertEquals("sbb가 무엇인가요?", question.getSubject());
    }
  }
}

id값으로 데이터를 조회하기 위해서는 findById 메서드를 사용해야 한다. 리턴타입이 Optional임에 주의하자. 

isPresent() 메서드는 값이 존재하는지 확인한다.

 

findBySubject

public interface QuestionRepository extends JpaRepository<Question, Integer> {
  Question findBySubject(String subject);
}
  @Test
  void testJpa() {
    Question q = this.questionRepository.findBySubject("sbb가 무엇인가요?");
    assertEquals(1, q.getId());
  }
}

 

findBy + 엔티티의 속성명과 같은 메서드를 작성하면 입력한 속성의 값으로 데이터를 조회할 수 있다. 기본 메서드가 제공되지는 않으므로 리포지터리 인터페이스를 변경해야만 한다. 

 

findBySubjectAndContent 

두 개의 열을 조회하기 위해서는 And 연산자를 사용한다. 마찬가지로 리포지토리에 메서드를 추가해야한다. 

public interface QuestionRepository extends JpaRepository<Question, Integer> {
  Question findBySubject(String subject);
  Question findBySubjectAndContent(String subject, String content);
}
  @Test
  void testJpa() {
    Question q = this.questionRepository.findBySubjectAndContent("sbb가 무엇인가요?", "sbb에 대해서 알고 싶습니다");
    assertEquals(1, q.getId());
  }
}

 

 

 

findBySubjectLike

Like는 특정 문자열을 포함한 데이터를 찾아낼 때 사용한다. 

public interface QuestionRepository extends JpaRepository<Question, Integer> {
  Question findBySubject(String subject);
  Question findBySubjectAndContent(String subject, String content);
  List<Question> findBySubjectLike(String subject);
}
  @Test
  void testJpa() {
    List<Question> qList = this.questionRepository.findBySubjectLike("sbb%");
    Question q = qList.get(0);
    assertEquals("sbb가 무엇인가요?", q.getSubject());
  }
}

 

sbb% : sbb로 시작하는 문자열

%sbb : sbb로 끝나는 문자열

%sbb% : sbb를 포함하는 문자열

 

질문 데이터 수정

  @Test
  void testJpa() {
    Optional<Question> oq = this.questionRepository.findById(1);
    assertTrue(oq.isPresent());
    Question q = oq.get();
    q.setSubject("수정된 제목");
    this.questionRepository.save(q);
  }
}

 

질문 데이터 삭제

 @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, questionRepository.count());

  }
}

 

답변 데이터 저장

@SpringBootTest
	@@ -13,12 +14,19 @@ class ApplicationTestsTest {
  @Autowired
  private QuestionRepository questionRepository;

  @Autowired
  private AnswerRepository answerRepository;

  @Test
  void testJpa() {
    Optional<Question> oq = questionRepository.findById(2);
    assertTrue(oq.isPresent());
    Question q = oq.get();

    Answer a = new Answer();
    a.setContent("네 자동으로 생성됩니다.");
    a.setQuestion(q);
    a.setCreateDate(LocalDateTime.now());
    this.answerRepository.save(a);
  }
}

 

답변 데이터 조회

 @Test
  void testJpa() {
    Optional<Answer> oa = this.answerRepository.findById(1);
    assertTrue(oa.isPresent());
    Answer a = oa.get();
    assertEquals(2, a.getQuestion().getId());
  }
}