๐ŸŒˆ[Spring] JPA: SQL์ฟผ๋ฆฌ๋ฌธ ์—†์ด ์ž๋ฐ”๋กœ๋งŒ DB๊ด€๋ฆฌ

์ „์ฃผ์€ยท2022๋…„ 12์›” 7์ผ
0
post-thumbnail

๐ŸŒˆJPA(Java Persistance API)

  • ์ž๋ฐ”์˜ ORM ๊ธฐ์ˆ  ํ‘œ์ค€
  • ๊ฐ์ฒด๋ฅผ DB์— ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•  ๋–„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ SQL์„ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋จ
  • JPA๊ฐ€ ๊ฐœ๋ฐœ์ž ๋Œ€์‹  ์ ์ ˆํ•œ SQL์„ ์ƒ์„ฑํ•ด์„œ DB์— ์ „๋‹ฌํ•˜๊ณ  ๊ฐ์ฒด๋ฅผ ์ž๋™์œผ๋กœ Mapping
  • ์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” ORM ํ”„๋ ˆ์ž„์›Œํฌ(Hibernate)๊ฐ€ ํƒ‘์ œ๋˜์–ด ์žˆ์Œ

๐Ÿ˜ Gradle

  • ์˜์กด์„ฑ ๊ด€๋ฆฌ์˜ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋Š” ๊ธฐ์ˆ 
  • maven์€ xml์„ ์‚ฌ์šฉ, gradle์€ groovy๋ผ๋Š” ์–ธ์–ด๋ฅผ ์‚ฌ์šฉ
  • ์˜คํ”ˆ์†Œ์Šค ๋นŒ๋“œ ๋„๊ตฌ(๊ฐœ๋ฐœ์‹œ ์ž๋™์œผ๋กœ ๋นŒ๋“œ๋ฅผ ๋„์™€์ฃผ๋Š” ํ”„๋กœ๊ทธ๋žจ)

๐Ÿ›ซ ORM(Object-Relational Mapping)

  • ๊ฐ์ฒด์™€ ๊ด€๊ณ„ํ˜• DB๋ฅผ ๋งคํ•‘
  • ๊ฐ์ฒด๋ฅผ ๋งˆ์น˜ ์ž๋ฐ” ์ปฌ๋ ‰์…˜์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ณ , ์ ์ ˆํ•œ SQL์„ ์ƒ์„ฑํ•ด์„œ DB๊ฐ์ฒด์— ์ €์žฅ

๐Ÿ lombok

  • ํ…Œ์ด๋ธ”์„ ๊ตฌ์กฐํ™”ํ•œ ํด๋ž˜์Šค(Entity, DTO, VO)์—์„œ getter/setter ๋ฉ”์†Œ๋“œ์™€ toString(), equals(), hashCode()๋“ฑ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

์–ด๋…ธํ…Œ์ด์…˜

@ Data: ์ž๋™์œผ๋กœ getter/setter๋ฅผ ์ง€์›
@ AllArgsConstructor: ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ง€์›ํ•˜๋Š” ์ƒ์„ฑ์ž ์ง€์›
@ NoArgsConstructor: ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ–์ง€ ์•Š๋Š” ์ƒ์„ฑ์ž๋ฅผ ์ง€์›
@ Entity: DB ํ…Œ์ด๋ธ”๊ณผ ์—ฐ๊ฒฐ
@ Builder: ๋ณตํ•ฉ ๊ฐ์ฒด์˜ ์ƒ์„ฑ ๊ณผ์ •๊ณผ ํ‘œํ˜„ ๋ฐฉ๋ฒ•์„ ๋ถ„๋ฆฌํ•˜์—ฌ ๋™์ผํ•œ ์ƒ์„ฑ ์ ˆ์ฐจ์—์„œ ์„œ๋กœ ๋‹ค๋ฅธ

โญ JPA Hibernate Entity ์ƒ์„ฑํ•˜๊ธฐ

์–ด๋…ธํ…Œ์ด์…˜

@Table: DB ํ…Œ์ด๋ธ”์˜ ์ด๋ฆ„์„ ๋ช…์‹œ(ํ…Œ์ด๋ธ”๋ช…๊ณผ ํด๋ž˜์Šค๋ช…์ด ๋™์ผํ•œ ๊ฒฝ์šฐ ์ƒ๋žต)
          admin_iser   ==    AdminUser
          ----------		-----------
        DB - ์Šค๋„ค์ดํฌํ‘œ๊ธฐ   Java - ์นด๋ฉœํ‘œ๊ธฐ
@Entity: DB์˜ ํ…Œ์ด๋ธ”์„ ๋œปํ•˜๋Š” ํด๋ž˜์Šค
@Id: primary key๋ฅผ ๋œปํ•จ
@GeneratedValue: primary key์˜ ํ‚ค ์ƒ์„ฑ ์ „๋žต(Strategy)์„ ์„ค์ •ํ•  ๋•Œ ์‚ฌ์šฉ
@Column: DB ํ•„๋“œ๋ช…์„ ๋ช…์‹œ(DBํ•„๋“œ๋ช…๊ณผ ์ž๋ฐ” ํด๋ž˜์Šค ํ•„๋“œ๋ช…์ด ๋™์ผํ•œ ๊ฒฝ์šฐ ์ƒ๋žต)
@Trasient: DB์—๋Š” ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ•„๋“œ์— ๋ช…์‹œ

๐ŸŒŒ JPA Repository

  • Spring Data JPA์˜ ๊ตฌํ˜„์ฒด์ธ Hibernate๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•œ API
  • JpaRepository์˜ ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ๋Š” <Entity, PKํƒ€์ž…>์„ ์ง€์ •.
  • ์ž๋™์œผ๋กœ ์Šคํ”„๋ง์˜ ๋นˆ(Bean)์œผ๋กœ ๋“ฑ๋ก๋จ
  • ๊ผญ ์กด์žฌํ•ด์•ผํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹˜!
public interface ์ธํ„ฐํŽ˜์ด์Šค๋ช… extends 
		JpaRepository<ํ…Œ์ด๋ธ”์„๊ตฌํ˜„ํ•œ class๋ช…, PKํƒ€์ž…(primary key์˜ ํƒ€์ž…>{
	SQL ์ฟผ๋ฆฌ๋ฅผ ๋Œ€์‹ ํ•  ๋ฉ”์†Œ๋“œ ์ •์˜
 }

๐Ÿ’ฏ Test(Junit)

  • Java์˜ ๋‹จ์œ„ ํ…Œ์ŠคํŒ… ๋„๊ตฌ
  • Test Class๋ฅผ ๊ทธ๋Œ€๋กœ ๋‚จ๊น€์œผ๋กœ์จ ์ถ”ํ›„ ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ• ๋ฐ ํด๋ž˜์Šค์˜ History๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ์Œ
  • @Test ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€ ํ›„ ์‚ฌ์šฉ

โœ” Optional

  • Inteager๋‚˜ Double ํด๋ž˜์Šค์™€ ๊ฐ™์ด 'T' ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ํฌ์žฅํ•˜๋Š” Wrapper Class ๋ชจ๋“  ํƒ€์ž…์„ ์ปค๋ฒ„ํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค
    (Optional์˜ ์ธ์Šคํ„ด์Šค๋Š” ๋ชจ๋“  ํƒ€์ž…์˜ ์ฐธ์กฐ ๋ณ€์ˆ˜๋ฅผ ์ €์žฅ ํ•  ์ˆ˜ ์žˆ๋‹ค.)

  • NullPointerException ์˜ˆ์™ธ๋ฅผ ์˜ˆ๋ฐฉํ•˜๊ธฐ ์œ„ํ•œ ์ข‹์€ ๋ฐฉ๋ฒ•

  • ์‹œ์ž‘(๊ฐ์ฒด์ƒ์„ฑ) -> ์ค‘๊ฐ„(Optional ๊ฐ์ฒด ๋ฐ˜ํ™˜) -> ๋(์ฒด์ด๋‹ ์ข…๋ฃŒ) 3๋‹จ๊ณ„๋กœ ๊ตฌํ˜„
    ๊ฐ์ฒด ์ƒ์„ฑ

  • ์‹œ์ž‘

    • of()
      null์ด ์•„๋‹Œ ๋ช…์‹œ๋œ ๊ฐ’์„ ์ €์žฅํ•œ optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
      null์ด ์ €์žฅ๋  ๊ฒฝ์šฐ, NullpointerException ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ด
    • ofNullable()
      null์ด ์•„๋‹Œ ๋ช…์‹œ๋œ ๊ฐ’์„ ์ €์žฅํ•œ optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
      null์ด ์ €์žฅ๋  ๊ฒฝ์šฐ, ๋น„์–ด์žˆ๋Š” oprional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
    • empty()
      ๋น„์–ด์žˆ๋Š” optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
  • ์ค‘๊ฐ„

    • filter()
      ์ž…๋ ฅ๊ฐ’์ด ์ฐธ์ด๋ฉด ๊ธฐ์กด optional ๊ฐ์ฒด๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜
      ์ž…๋ ฅ๊ฐ’์ด ๊ฑฐ์ง“์ด๋ฉด ๋น„์–ด์žˆ๋Š” optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
      โœ” ์ž…๋ ฅ๊ฐ’์€ functional interface๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํŠน์ • ์—ฐ์‚ฐ์œผ๋กœ ์ฒดํฌํ•˜์—ฌ boolean๊ฐ’์„ ๋ฐ˜ํ™˜ํ•จ(ํŠน์ • ์—ฐ์‚ฐ์ด๋ž€ ๋žŒ๋‹ค์‹์œผ๋กœ ํ‘œํ˜„ํ•จ)
    • map()
      optional ๊ฐ์ฒด์˜ ์ €์žฅ๋œ ๊ฐ’์„ map() ๋‚ด์˜ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ฐ˜ํ™˜ํ•˜๊ณ , ๋ณ€ํ™˜๊ฐ’์„ ๋‹ด์€ optional ๊ฐ์ฒด์— ๋ฐ˜ํ™˜
  • ๋

    • ifPresent()
      optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด, ์ €์žฅ๋œ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ifPresent() ๋‚ด์˜ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰
      optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด, ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜(์•„๋ฌด ์—ฐ์‚ฐ๋„ ์ˆ˜ํ–‰X)
    • isPresent()
      optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด, true๋ฅผ ๋ฐ˜ํ™˜
      optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด, false๋ฅผ ๋ฐ˜ํ™˜
    • get()
      optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด, ์ €์žฅ๋œ ๊ฐ’์„ ๊บผ๋‚ด ๋ฐ˜ํ™˜
      optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด, NoSuchElementException์„ ๋ฐ˜ํ™˜
    • orElse()
      optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด, ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜(์•„๋ฌด ์—ฐ์‚ฐ ์ˆ˜ํ–‰ X)
      optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด, ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ œ๊ณตํ•  ๊ฐ์ฒด๋ฅผ ์ง€์ •
    • orElseGet()
      optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด, ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜(์•„๋ฌด ์—ฐ์‚ฐ ์ˆ˜ํ–‰X)
      optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด, ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ œ๊ณตํ•  ๊ณต๊ธ‰ ํ•จ์ˆ˜๋ฅผ ์ง€์ •(๋žŒ๋‹ค ํ‘œํ˜„์‹์˜ ๊ฒฐ๊ณผ๊ฐ’ ๋ฐ˜ํ™˜)
    • orElseThrow()
      optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด, ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜(์•„๋ฌด ์—ฐ์‚ฐ ์ˆ˜ํ–‰ X)
      optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด, ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ œ๊ณตํ•  ์˜ˆ์™ธ ๊ณต๊ธ‰์ž ํ•จ์ˆ˜ ์ง€์ •ํ•˜์—ฌ ์˜ˆ์™ธ Throw

    ๐Ÿฅจ orElse๋Š” optional ๊ฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๋˜, ๋น„์—ˆ๋˜ ๋ฌด์กฐ๊ฑด ์‹คํ–‰!
    ๐Ÿฅจ orElseGet์€ ๋น„์–ด์žˆ์„ ๋•Œ๋งŒ ์‹คํ–‰!

๐Ÿ’ฌ ์˜ˆ์ œ

main > java > com.ํŒจํ‚ค์ง€.ํ”„๋กœ์ ํŠธ.model.entity

package com.koreait.day3.model.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.time.LocalDateTime;

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data       
@Builder  
public class AdminUser {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String userid;
    private String userpw;
    private String name;
    private String status;
    private LocalDateTime lastLoginAt;
    private LocalDateTime regDate;
}

main > java > com.ํŒจํ‚ค์ง€.ํ”„๋กœ์ ํŠธ.repository

package com.koreait.day3.repository;

import com.koreait.day3.model.entity.AdminUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AdminUserRepository extends JpaRepository<AdminUser, Long>{

}

Test > java > com.ํŒจํ‚ค์ง€.ํ”„๋กœ์ ํŠธ > repository

package com.koreait.day3.repository;


import com.koreait.day3.Day3ApplicationTests;
import com.koreait.day3.model.entity.AdminUser;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDateTime;
import java.util.Optional;

public class AdminUserRepositoryTest extends Day3ApplicationTests {
    //Day3ApplicationTests์ด public class๊ฐ€ ์•„๋‹ˆ๋ผ์„œ ์ž„ํฌํŠธ ํ•ด์ฃผ๋ ค๋ฉด public์œผ๋กœ ๋ฐ”๊ฟ”์ค˜์•ผํ•จ
    @Autowired
    private AdminUserRepository adminUserRepository;

    @Test
    public void create(){
         AdminUser adminUser = AdminUser.builder().userid("banana")
                 .userpw("2222").name("๋ฐ˜ํ•˜๋‚˜").build();
         AdminUser newAdminUser = adminUserRepository.save(adminUser);
    }

    @Test
    public void update(){
        Optional<AdminUser> adminUser = adminUserRepository.findById(1L); //ID๋กœ select
        adminUser.ifPresent(
                selectUsers  -> {
                    //๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๋งŒํผ ์ด ํ–‰๋™์„ ํ•ด๋‹ฌ๋ผ!
                    selectUsers.setUserpw("1004");
                    selectUsers.setLastLoginAt(LocalDateTime.now());
                    selectUsers.setName("์‚ฌ๊ณผํ‚ด");
                    adminUserRepository.save(selectUsers);
                }
        );
    }

    @Test
    public void delete(){
        Optional<AdminUser> adminUser = adminUserRepository.findById(1L);
        adminUser.ifPresent(
                selectUsers ->{
                    adminUserRepository.delete(selectUsers);
                }

        );
    }
}

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