๐Ÿต java

JAVA | JPA Repository์˜ ์‚ฌ์šฉ๋ฒ•๊ณผ ๋ฉ”์„œ๋“œ

c0zi 2023. 7. 14. 17:38

JPA๊ฐ€ ๋ฌด์—‡์ผ๊นŒ ?


JPA๋Š” ์ด์ „์— ์ •๋ฆฌํ•ด๋ณด์•˜์œผ๋‹ˆ ์ด๋ฒˆ์—๋Š” JPA Repository์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ณ ์ž ํ•œ๋‹ค.

 

โ–ผ JPA ์ •๋ฆฌ๊ธ€

 

 

JAVA | JPA ์•Œ์•„๋ณด๊ธฐ (JPA, JDBC, Hibernate & JPA)

1. JPA Java Persistence API์˜ ์•ฝ์ž๋กœ, ์ž๋ฐ” ์ง„์˜์—์„œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜ ๋ฐ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋งคํ•‘ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค Persistence -> ์˜๊ตฌ์ ์ธ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ

codingdialee.tistory.com

 


JPA Repository


  • Java ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ฃผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋ฉฐ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ CRUD(Create, Read, Update, Delete) ์ž‘์—…์„ ์ˆ˜ํ–‰

์˜ˆ์‹œ๋ฅผ ๋“ค์ž๋ฉด, ๊ฐ์ฒด์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •, ์ €์žฅ, ์‚ญ์ œ ๋“ฑ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๋•Œ Spring JPA์—์„œ ์ œ๊ณตํ•˜๋Š” Repository๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•ด ํ•ด๋‹น Entity์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

JPA Repository๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ EntityManager๊ฐ€ ์ง์ ‘ ๋Œ€์ƒ Entity์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— Repository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š๊ณ ๋„ ์ง์ ‘ EntityManger๋ฅผ ์‚ฌ์šฉํ•ด Persistance Layer๋ฅผ ๊ตฌํ˜„ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ Spring JPA์—์„œ Repository์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์ฒด๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑ์‹œ์ผœ ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋ณ„๋„์˜ ๊ตฌํ˜„์ฒด๋ฅผ ๋”ฐ๋กœ ์ƒ์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

 

* persistance layer : ํ”„๋กœ๊ทธ๋žจ์˜ ์•„ํ‚คํ…์ฒ˜์—์„œ, ๋ฐ์ดํ„ฐ์— ์˜์†์„ฑ์„ ๋ถ€์—ฌํ•ด์ฃผ๋Š” ๊ณ„์ธต

 

๐Ÿ“Œ repository๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

 

  • ๊ฐ์ฒด์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ„์˜ ๋งคํ•‘ ๊ด€๋ฆฌ : JPA ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋Š” ORM(Object-Relational Mapping)์„ ํ†ตํ•ด ๊ฐ์ฒด์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ„์˜ ๋งคํ•‘์„ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ, ๊ฐ์ฒด ์ง€ํ–ฅ์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

  • CRUD ์ž‘์—… ๊ฐ„์†Œํ™” : JPA ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ CRUD(Create, Read, Update, Delete) ์ž‘์—…์„ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ํ†ตํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•๋Š”๋‹ค. JPA๋Š” ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์— ๋”ฐ๋ผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์กฐํšŒ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด ๊ฐœ๋ฐœ์ž๋Š” SQL ์ฟผ๋ฆฌ ์ž‘์„ฑ์— ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š๊ณ ๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

  • ์œ ์—ฐํ•œ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ : JPA ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋Š” ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ์™€ @Query ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ ์ธ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.๊ฐœ๋ฐœ์ž๋Š” ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ•„์š”ํ•œ ๊ฒ€์ƒ‰ ์กฐ๊ฑด์— ๋งž๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๊ณ  ํ•„ํ„ฐ๋งํ•  ์ˆ˜ ์žˆ๋‹ค.

 

  • ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ : JPA ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋Š” ํŠธ๋žœ์žญ์…˜์„ ๊ด€๋ฆฌํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์˜ ์ผ๊ด€์„ฑ๊ณผ ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•œ๋‹ค. ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ JPA ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, ๋ณ€๊ฒฝ๋œ ๋ฐ์ดํ„ฐ๋Š” ํŠธ๋žœ์žญ์…˜์ด ์ปค๋ฐ‹๋  ๋•Œ๊นŒ์ง€ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ €์žฅ๋˜๋ฉฐ, ๋กค๋ฐฑ์ด ๋ฐœ์ƒํ•˜๋ฉด ๋ณ€๊ฒฝ ์‚ฌํ•ญ๋„ ๋กค๋ฐฑ๋œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๊ณ  ๋ฐ์ดํ„ฐ ์กฐ์ž‘์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

  • ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ : JPA ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…๊ณผ ๊ด€๋ จ๋œ ๋กœ์ง์„ ๋ณ„๋„์˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํด๋ž˜์Šค๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ์ด ํ–ฅ์ƒ๋˜๊ณ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ จ ๋กœ์ง์„ ์ค‘์•™ ์ง‘์ค‘ํ™”ํ•˜์—ฌ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

 

JPA Repository๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ์ถ”์ƒํ™”ํ•˜๊ณ , ๊ฐ์ฒด ์ง€ํ–ฅ์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ƒํ˜ธ ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํŽธ๋ฆฌํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” ๋” ๊ฐ„ํŽธํ•˜๊ณ  ์ƒ์‚ฐ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ๋„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

 


1. JpaRepository ์ƒ์„ฑ ๊ทœ์น™

 

package com.mysite.sbb;

import org.springframework.data.jpa.repository.JpaRepository;

public interface QuestionRepository extends JpaRepository<Question, Integer> {

}

 

์˜ˆ์‹œ๋กœ QuestionRepository๋ฅผ ์ƒ์„ฑํ•˜์˜€์„ ๋•Œ, ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด JpaRepository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†ํ•˜์˜€๋‹ค. JpaRepository๋ฅผ ์ƒ์†ํ•  ๋•Œ๋Š” ์ œ๋„ค๋ฆญ์Šค ํƒ€์ž…์œผ๋กœ <Question, Integer> ์ฒ˜๋Ÿผ ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ์˜ ๋Œ€์ƒ์ด ๋˜๋Š” ์—”ํ‹ฐํ‹ฐ์˜ ํƒ€์ž…(Question)๊ณผ ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ์˜ PK์˜ ์†์„ฑ ํƒ€์ž…(Integer)์„ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค. ์ด๊ฒƒ์€ JpaRepository๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๊ทœ์น™์ด๋‹ค.

 

pulibc interface [Repository ์ด๋ฆ„] extends JpaRepository<[๊ฐ์ฒด ํƒ€์ž…], [๊ฐ์ฒด PK ์†์„ฑ ํƒ€์ž…]> {}

 


2. ๋ฐ์ดํ„ฐ ์ €์žฅํ•˜๊ธฐ - save()

 

์ž‘์„ฑํ•œ repository๋ฅผ ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ ์œ„ํ•ด JUnit ๊ธฐ๋ฐ˜์˜ ์Šคํ”„๋ง๋ถ€ํŠธ์˜ ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

 

import java.time.LocalDateTime;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;


@SpringBootTest
class SbbApplicationTests {

    @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);  // ๋‘๋ฒˆ์งธ ์งˆ๋ฌธ ์ €์žฅ
    }
}

 

์œ„์˜ ๋ฉ”์„œ๋“œ๋Š” q1, q2 ๋ผ๋Š” Question ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , QuestionRepository๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ทธ ๊ฐ’์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

 

Line 20์„ ๋ณด๋ฉด, save() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ €์žฅํ•œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. insert()์™€ update() ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

 

@Autowired ์• ๋„ˆํ…Œ์ด์…˜: ์Šคํ”„๋ง์˜ DI ๊ธฐ๋Šฅ์œผ๋กœ questionRepository ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง์ด ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด ์ค€๋‹ค.
@Test ์• ๋„ˆํ…Œ์ด์…˜ :  testJpa ๋ฉ”์„œ๋“œ๊ฐ€ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ์ž„์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์œ„ ํด๋ž˜์Šค๋ฅผ JUnit์œผ๋กœ ์‹คํ–‰ํ•˜๋ฉด @Test ์• ๋„ˆํ…Œ์ด์…˜์ด ๋ถ™์€ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
@Autowired
๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ์Šคํ”„๋ง์˜ ์• ๋„ˆํ…Œ์ด์…˜์ด๋‹ค. ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ์‹์—๋Š” @Autowired ์™ธ์— Setter ๋˜๋Š” ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด ์žˆ๋‹ค. ์ˆœํ™˜์ฐธ์กฐ ๋ฌธ์ œ์™€ ๊ฐ™์€ ์ด์œ ๋กœ @Autowired ๋ณด๋‹ค๋Š” ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ๊ฐ์ฒด ์ฃผ์ž…๋ฐฉ์‹์ด ๊ถŒ์žฅ๋œ๋‹ค. ํ•˜์ง€๋งŒ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ์—๋Š” ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ๊ฐ์ฒด์˜ ์ฃผ์ž…์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ์‹œ์—๋งŒ @Autowired๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ค์ œ ์ฝ”๋“œ ์ž‘์„ฑ์‹œ์—๋Š” ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ๊ฐ์ฒด ์ฃผ์ž…๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค.

 

* DI(Dependency Injection) - ์Šคํ”„๋ง์ด ๊ฐ์ฒด๋ฅผ ๋Œ€์‹  ์ƒ์„ฑํ•˜์—ฌ ์ฃผ์ž…ํ•œ๋‹ค.

 


3. ๋ฐ์ดํ„ฐ ์กฐํšŒํ•˜๊ธฐ - findAll()

 

์ด๋ฒˆ์—๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ด ๋ณด์ž.

 

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
class SbbApplicationTests {

    @Autowired
    private QuestionRepository questionRepository;

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

        Question q = all.get(0);
        assertEquals("sbb๊ฐ€ ๋ฌด์—‡์ธ๊ฐ€์š”?", q.getSubject());
    }
}

 

question ํ…Œ์ด๋ธ”์— ์ €์žฅ๋œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ์˜ findAll ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

 

findAll : DB์—์„œ ์ „์ฒด๊ฐ’์„ list๋กœ ๋ถˆ๋Ÿฌ์˜ด

 

JUnit & ๋ฉ”์„œ๋“œ ์„ค๋ช…

>> ์ด 2๊ฑด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ์˜ ์‚ฌ์ด์ฆˆ๋Š” 2๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค. ๋ฐ์ดํ„ฐ ์‚ฌ์ด์ฆˆ๊ฐ€ 2์ธ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด JUnit์˜ assertEquals ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค. assertEquals๋Š” assertEquals(๊ธฐ๋Œ€๊ฐ’, ์‹ค์ œ๊ฐ’)์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๊ณ  ๊ธฐ๋Œ€๊ฐ’๊ณผ ์‹ค์ œ๊ฐ’์ด ๋™์ผํ•œ์ง€๋ฅผ ์กฐ์‚ฌํ•œ๋‹ค. ๋งŒ์•ฝ ๊ธฐ๋Œ€๊ฐ’๊ณผ ์‹ค์ œ๊ฐ’์ด ๋™์ผํ•˜์ง€ ์•Š๋‹ค๋ฉด ํ…Œ์ŠคํŠธ๋Š” ์‹คํŒจ๋กœ ์ฒ˜๋ฆฌ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ €์žฅํ•œ ์ฒซ๋ฒˆ์งธ ๋ฐ์ดํ„ฐ์˜ ์ œ๋ชฉ์ด "sbb๊ฐ€ ๋ฌด์—‡์ธ๊ฐ€์š”?"์™€ ์ผ์น˜ํ•˜๋Š”์ง€๋„ ํ…Œ์ŠคํŠธํ–ˆ๋‹ค.

 

findBy__()

 

์ด๋ฒˆ์—๋Š” Question ์—”ํ‹ฐํ‹ฐ์˜ Id๊ฐ’์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ด ๋ณด์ž.

 

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
class SbbApplicationTests {

    @Autowired
    private QuestionRepository questionRepository;

    @Test
    void testJpa() {
        Optional<Question> oq = this.questionRepository.findById(1);
        if(oq.isPresent()) {
            Question q = oq.get();
            assertEquals("sbb๊ฐ€ ๋ฌด์—‡์ธ๊ฐ€์š”?", q.getSubject());
        }
    }
}

 

id ๊ฐ’์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ์˜ findById ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ํ•˜์ง€๋งŒ findById์˜ ๋ฆฌํ„ด ํƒ€์ž…์€ Question์ด ์•„๋‹Œ Optional์ž„์— ์ฃผ์˜ํ•˜์ž. Optional์€ null ์ฒ˜๋ฆฌ๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ํด๋ž˜์Šค๋กœ ์œ„์™€ ๊ฐ™์ด isPresent๋กœ null์ด ์•„๋‹Œ์ง€๋ฅผ ํ™•์ธํ•œ ํ›„์— get์œผ๋กœ ์‹ค์ œ Question ๊ฐ์ฒด ๊ฐ’์„ ์–ป์–ด์•ผ ํ•œ๋‹ค.

 

๋‹ค์Œ๊ณผ ๊ฐ™์ด findBy__์—์„œ ๋’ท๋ถ€๋ถ„์— ์ •์˜ํ•œ Entity ์ด๋ฆ„์„ ๋ถ™์ด๋ฉด ํŠน์ • entity์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.
ex) findByProductId()

 

findBySubject

 

๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด QuestionRepository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค.

 

public interface QuestionRepository extends JpaRepository<Question, Integer> {
    Question findBySubject(String subject);
}

 

๊ทธ๋Ÿฌ๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ ์ œ๋ชฉ์œผ๋กœ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

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
class SbbApplicationTests {

    @Autowired
    private QuestionRepository questionRepository;

    @Test
    void testJpa() {
        Question q = this.questionRepository.findBySubject("sbb๊ฐ€ ๋ฌด์—‡์ธ๊ฐ€์š”?");
        assertEquals(1, q.getId());
    }
}

 

์ด๋Ÿฌํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด ํ…Œ์ŠคํŠธ๋Š” ์ž˜ ํ†ต๊ณผ๋œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ฝ”๋“œ๋ฅผ ๋ณด๋‹ค๋ณด๋ฉด "์ธํ„ฐํŽ˜์ด์Šค์— findBySubject ๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธ๋งŒ ํ•˜๊ณ  ๊ตฌํ˜„์€ ํ•˜์ง€ ์•Š์•˜๋Š”๋ฐ ๋„๋Œ€์ฒด ์–ด๋–ป๊ฒŒ ์‹คํ–‰์ด ๋˜๋Š” ๊ฑฐ์ง€?"๋ผ๋Š” ์˜๋ฌธ์ด ์ƒ๊ธด๋‹ค. 

 

์ด๋Š” JpaRepository๋ฅผ ์ƒ์†ํ•œ QuestionRepository ๊ฐ์ฒด ๋•Œ๋ฌธ์— ๊ฐ€๋Šฅํ•œ ์ผ์ด๋‹ค. (DI์— ์˜ํ•ด ์Šคํ”„๋ง์ด ์ž๋™์œผ๋กœ QuestionRepository ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ด ๋•Œ ํ”„๋ก์‹œ ํŒจํ„ด์ด ์‚ฌ์šฉ๋œ๋‹ค๊ณ  ํ•œ๋‹ค.) ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋ ๋•Œ JPA๊ฐ€ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ช…์„ ๋ถ„์„ํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹คํ–‰ํ•œ๋‹ค.

 

์ฆ‰, findBy + ์—”ํ‹ฐํ‹ฐ์˜ ์†์„ฑ๋ช…(์˜ˆ:findBySubject)๊ณผ ๊ฐ™์€ ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ํ•ด๋‹น ์†์„ฑ์˜ ๊ฐ’์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ• ์ˆ˜ ์žˆ๋‹ค. findBySubject ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ• ๋•Œ ์‹ค์ œ๋กœ ์‹คํ–‰๋˜๋Š” ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

์ด๋ฏธ์ง€ ์ถœ์ฒ˜ : ์œ„ํ‚ค ๋…์Šค

 

์ด์™ธ์—๋„ ์ฟผ๋ฆฌ์˜ ์กฐ๊ฑด์„ ๋ณ€๊ฒฝํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ์ˆ˜๋„ ์žˆ๋Š”๋ฐ, ์ด๋Ÿฌํ•œ ๋ฉ”์„œ๋“œ์˜ ๋ช…๋ช…๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

 

ํ•ญ๋ชฉ ์„ค๋ช… ์˜ˆ์ œ
And ์—ฌ๋Ÿฌ ์ปฌ๋Ÿผ์„ and ์กฐ๊ฑด์œผ๋กœ ๊ฒ€์ƒ‰ findBySubjectAndContetnt(Stringsubject, String content)
Or ์—ฌ๋Ÿฌ ์ปฌ๋Ÿผ์„ or ์กฐ๊ฑด์œผ๋กœ ๊ฒ€์ƒ‰ findBySubjectOrContent(Stringsubject, String content)
Between ์ปฌ๋Ÿผ์„ between์œผ๋กœ ๊ฒ€์ƒ‰ findByCreateDateBetween(LocalDateTime fromData,
LocalDateTime toDate)
LessThan ์ž‘์€ ํ•ญ๋ชฉ ๊ฒ€์ƒ‰ findByIdLessThan(Integer id)
GreaterThanEqual ํฌ๊ฑฐ๋‚˜ ๊ฐ™์€ ํ•ญ๋ชฉ ๊ฒ€์ƒ‰ findByIdGreaterThanEqual(Integer id)
Like like ๊ฒ€์ƒ‰ findBySubjectLike(String subject)
In ์—ฌ๋Ÿฌ ๊ฐ’ ์ค‘์— ํ•˜๋‚˜์ธ ํ•ญ๋ชฉ ๊ฒ€์ƒ‰ findBySubjectIn(String[] subjects)
OrderBy ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ์ •๋ ฌํ•˜์—ฌ ์ „๋‹ฌ findBySubjectOrderByCreateDateAsc(String subject)

 


4. ๋ฐ์ดํ„ฐ ์ˆ˜์ •ํ•˜๊ธฐ

 

์ด๋ฒˆ์—๋Š” ์งˆ๋ฌธ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ๋ณด์ž.

 

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
class SbbApplicationTests {

    @Autowired
    private QuestionRepository questionRepository;

    @Test
    void testJpa() {
        Optional<Question> oq = this.questionRepository.findById(1);
        assertTrue(oq.isPresent());
        Question q = oq.get();
        q.setSubject("์ˆ˜์ •๋œ ์ œ๋ชฉ");
        this.questionRepository.save(q);
    }
}

 

 

์งˆ๋ฌธ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒ(findById)ํ•œ ๋‹ค์Œ subject๋ฅผ "์ˆ˜์ •๋œ ์ œ๋ชฉ" ์ด๋ผ๋Š” ๊ฐ’์œผ๋กœ ์ˆ˜์ •ํ–ˆ๋‹ค. ๋ณ€๊ฒฝ๋œ Question ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” this.questionRepository.save(q) ์ฒ˜๋Ÿผ ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ์˜ save ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. (์ €์žฅ๊ณผ ๋™์ผ)

 


5. ๋ฐ์ดํ„ฐ ์‚ญ์ œํ•˜๊ธฐ

 

์ด์–ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•˜๋Š” ๊ฒƒ๋„ ์‹ค์Šตํ•ด ๋ณด์ž.

 

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
class SbbApplicationTests {

    @Autowired
    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://akdl911215.tistory.com/307

 

JPA Repository๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

ํ•„์ž๋Š” ๋ฉด์ ‘์„ ๋ณด๊ณ  ์™”๋‹ค. ๋งŽ์€ ์งˆ๋ฌธ๊ณผ ์ด์•ผ๊ธฐ๊ฐ€ ์˜ค๊ณ  ๊ฐ”์ง€๋งŒ, ๊ทธ ์ค‘ ํ•œ๊ฐœ๋Š” JPA Repository๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๊ฐ€ ๋ฌด์—‡์ธ๊ฐ€? ๋ผ๋Š” ์งˆ๋ฌธ์ด ๊ธฐ์–ต์— ๋‚จ์•„์„œ ๊ธฐ๋กํ•ด๋‘”๋‹ค. ํ•„์ž๋Š” JPA Repository๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด

akdl911215.tistory.com

https://wikidocs.net/160890#_1

 

2-05 ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ

* `[์™„์„ฑ ์†Œ์Šค]` : [https://github.com/pahkey/sbb3/tree/2-05](https://github.com/pahkey/sbb3/tree/2-05) …

wikidocs.net

https://zara49.tistory.com/130

 

[JPA] JPA Repository ๋ฉ”์„œ๋“œ ๋ช…๋ช…๊ทœ์น™

JPA๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ฟผ๋ฆฌ๋ฅผ ์—ด์‹ฌํžˆ ์งœ๋Š”๊ฒƒ์„ ๋Œ€์‹ ํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ํ‘œํ˜„ํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ค ํ˜•ํƒœ๋กœ ๋ฉ”์†Œ๋“œ ์ด๋ฆ„์„ ๋ถ™์ด๋ฉด ๋˜๋Š”์ง€, ๋ช…๋ช… ๊ทœ์น™์— ๋Œ€ํ•ด ๊ฐ„๋žตํ•˜๊ฒŒ ์ •๋ฆฌํ•ด๋‘์ž.

zara49.tistory.com