Spring-boot JPA

์žญ์žญ์ดยท2021๋…„ 4์›” 21์ผ
1

Spring-boot

๋ชฉ๋ก ๋ณด๊ธฐ
4/11
post-thumbnail

Spring-boot JPA

๐ŸŽ ๋ชฉ์ฐจ

0. ๊ฐœ์š”

JPA (Java Persistence API) Spring-boot์—์„œ RDB์˜ ๊ด€๋ฆฌ๋ฅผ ์šฉ์ดํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” API์ด๋‹ค. (= ์ž๋ฐ” ํ‘œ์ค€ ORM)
ORM(Object Relational Mapping): DB์™€ ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ๋ฒ•

1. Dependency ์ถ”๊ฐ€

build.gradle์— ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'com.h2database:h2'
}
  • spring-boot-starter-data-jpa
    • JPA ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • h2
    • ์ธ๋ฉ”๋ชจ๋ฆฌ RDB

2. Entity ์ž‘์„ฑ

  1. package ์ƒ์„ฑ
    domain/postsํด๋”๋ฅผ ๋งŒ๋“ ๋‹ค
  2. entity class ์ƒ์„ฑ
    ํ•ด๋‹น ํด๋” ์•„๋ž˜์— Posts.java๋ฅผ ๋งŒ๋“ ๋‹ค.
package com.example.demo.domain.posts;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;


@Getter
@NoArgsConstructor                                       
@Entity                                                   
public class Posts {

  @Id  
  @GeneratedValue(strategy = GenerationType.IDENTITY)     
  private Long id;

  @Column(length = 500, nullable = false)                   
  private String title;

  @Column(columnDefinition = "TEXT", nullable = false)
  private String content;

  private String author;

  @Builder
  public Posts(String title, String content, String author){
    this.title = title;
    this.content = content;
    this.author = author;
  }
}
  • Entity ํด๋ž˜์Šค์—์„œ๋Š” ์ ˆ๋Œ€ Setter method๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค.
    • ๋Œ€์‹  ํ•ด๋‹น ํ•„๋“œ์˜ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ• ๋•Œ ๋ช…ํ™•ํžˆ ๊ทธ ๋ชฉ์ ๊ณผ ์˜๋„๋ฅผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋Š” method๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.
    • DB ์‚ฝ์ž…: ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์‚ฝ์ž…ํ•œ๋‹ค.
    • DB ๋ณ€๊ฒฝ: ํ•ด๋‹น ์ด๋ฒคํŠธ์— ๋งž๋Š” public method ํ˜ธ์ถœ
  • @NoArgsConstructor
    • ๊ธฐ๋ณธ ์ƒ์„ฑ์ž ์ž๋™ ์ถ”๊ฐ€
    • public Post(){} ์™€ ๋™์ผํšจ๊ณผ
  • @Entity
    • ํ…Œ์ด๋ธ”๊ณผ ๋งํฌ๋  ํด๋ž˜์Šค์ž„์„ ๋ช…์‹œ
    • default: CamelCase -> under_score_naming ์œผ๋กœ ํ…Œ์ด๋ธ” ์ด๋ฆ„ ๋งค์นญ
  • @Id
    • ํ•ด๋‹น ํ…Œ์ด๋ธ”์˜ PKํ•„๋“œ
  • @GeneratedValue(strategy = GenerationType.IDENTITY)
    • PK์˜ ์ƒ์„ฑ ๊ทœ์น™์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.
    • ์Šคํ”„๋ง๋ถ€ํŠธ 2.0์—์„œ๋Š” GenerationType.IDENTITY ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•ด์•ผ auto_increment
    • GenerationType.AUTO (default) ์˜ต์…˜์€ ํ…Œ์ด๋ธ”์—์„œ ์‹œํ€€์Šค ๊ฐ’์„ ๊ฐ€์ ธ์™€ ์—…๋ฐ์ดํŠธํ•˜๊ณ , ํ•ด๋‹น ๊ฐ’์œผ๋กœ id ์ƒ์„ฑ
  • @Column(length = 500, nullable = false)
    • ํ…Œ์ด๋ธ”์˜ ์นผ๋Ÿผ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.
    • ๊ตณ์ด ์„ ์–ธํ•˜์ง€ ์•Š์•„๋„ ์ด ํด๋ž˜์Šค์˜ ๋ชจ๋“  ํ•„๋“œ๋Š” ์นผ๋Ÿผ์ด ๋œ๋‹ค.
    • ์ถ”๊ฐ€๋กœ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•œ ์˜ต์…˜์ด ์žˆ์„๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
  • @Builder
    • ์ƒ์„ฑ์ž ์ƒ๋‹จ์— ์„ ์–ธ ์‹œ ์ƒ์„ฑ์ž์— ํฌํ•จ๋œ ํ•„๋“œ๋งŒ ๋นŒ๋”์— ํฌํ•จ

3. Repository ์ž‘์„ฑ

  1. repository class ์ƒ์„ฑ
    domain/posts ํด๋” ์•„๋ž˜์— PostsRepository.java๋ฅผ ๋งŒ๋“ ๋‹ค.
package com.example.demo.domain.posts;

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

public interface PostsRepository extends JpaRepository<Posts, Long>{
}
  • Posts ํด๋ž˜์Šค๋กœ DB๋ฅผ ์ ‘๊ทผํ•˜๊ฒŒ ํ•ด์ค„ JPA Repository (๋ฐ˜๋“œ์‹œ Entity ํด๋ž˜์Šค์™€ ํ•จ๊ป˜ ์œ„์น˜)
  • MyBatis์—์„œ์˜ DAO. JPA์—์„œ๋Š” Repository๋ผ๊ณ  ๋ถ€๋ฆ„
  • interface๋ฅผ ์ƒ์„ฑ ํ›„ JpaRepository<Entity, PK>๋ฅผ ์ƒ์†ํ•˜๋ฉด ๊ธฐ๋ณธ์ ์ธ CRUD method๊ฐ€ ์ž๋™ ์ƒ์„ฑ

4. application.properties ์ˆ˜์ •

application.properties์— ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

# ์‹คํ–‰๋˜๋Š” ์ฟผ๋ฆฌ ๋กœ๊ทธ
spring.jpa.show-sql=true
# H2๋ฌธ๋ฒ• ๋กœ๊ทธ๋ฅผ MySQL๋ฌธ๋ฒ• ๋กœ๊ทธ๋กœ ์ถœ๋ ฅ
spring.jpa.properties.hibernate.dialect.storage_engine=innodb
spring.datasource.hikari.jdbc-url=jdbc:h2:mem:testdb;MODE=MYSQL
spring.datasource.hikari.username=rivernine

5. ํ…Œ์ŠคํŠธ์ฝ”๋“œ ์ž‘์„ฑ

  1. package ์ƒ์„ฑ
    test์•„๋ž˜์— ๋™์ผ ๊ตฌ์กฐ์˜ ํด๋”๋ฅผ ๋งŒ๋“ ๋‹ค. domain/posts
  2. test class ์ƒ์„ฑ
    ํ•ด๋‹น ํด๋” ์•„๋ž˜์— PostsRepositoryTest.java๋ฅผ ๋งŒ๋“ ๋‹ค.
package com.example.demo.domain.posts;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.List;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@ExtendWith(MockitoExtension.class)
@SpringBootTest
public class PostsRepositoryTest {
  
  @Autowired
  PostsRepository postsRepository;
  
  @AfterEach
  public void cleanup() {
    postsRepository.deleteAll();
  }

  @Test
  public void board_save() {
    String title = "test_title";
    String content = "test_content";
    
    postsRepository.save(Posts.builder()
                                .title(title)
                                .content(content)
                                .author("test@gmail.com")
                                .build());
    
    List<Posts> postsList = postsRepository.findAll();

    Posts posts = postsList.get(0);
    assertThat(posts.getTitle()).isEqualTo(title);
    assertThat(posts.getContent()).isEqualTo(content);
  }
}
  • @AfterEach
    • Junit์—์„œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚  ๋•Œ๋งˆ๋‹ค ์ˆ˜ํ–‰๋˜๋Š” method
    • ๋ฐ์ดํ„ฐ ์นจ๋ฒ”์„ ๋ง‰๊ธฐ์œ„ํ•ด ์‚ฌ์šฉ
    • H2์— ๋ฐ์ดํ„ฐ๊ฐ€ ๊ทธ๋Œ€๋กœ ๋‚จ์•„์žˆ์–ด ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€
  • postsRepository.save()
    • posts ํ…Œ์ด๋ธ”์— insert/update ์‹คํ–‰
  • postsRepository.findAll()
    • posts ํ…Œ์ด๋ธ”์— ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒ

4. ํ…Œ์ŠคํŠธ

Run Test๋ฅผ ๋ˆ„๋ฅด๋ฉด unit test๋ฅผ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. ๊ฒฐ๊ณผ ํ™•์ธ
    ๋””๋ฒ„ํฌ ์ฝ˜์†”์„ ํ™•์ธํ•˜์ž.
    Spring-boot application์ด ์‹คํ–‰๋˜๊ณ  Hibernate์˜ ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ธ๋ฉ”๋ชจ๋ฆฌ DB๋ฅผ ๋งŒ๋“ค์–ด ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ณ  @AfterEach๋กœ ์ง€์ •ํ•ด์ค€ method๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

5. ์‹คํ–‰

# ๋นŒ๋“œ
./gradlew build
# Spring-boot ์‹คํ–‰
java -jar ./build/lib/*.jar

๋ชจ๋“  ์†Œ์Šค๋Š” ๊นƒํ—ˆ๋ธŒ์— ์˜ฌ๋ ค๋†“์•˜๋‹ค.
์ฐธ๊ณ ์„œ์ : ์Šคํ”„๋ง๋ถ€ํŠธ์™€ AWS๋กœ ํ˜ผ์ž ๊ตฌํ˜„ํ•˜๋Š” ์›น ์„œ๋น„์Šค

0๊ฐœ์˜ ๋Œ“๊ธ€