[Spring Boot] JPA

2021. 8. 18. 08:00ใ†Back-End ์ž‘์—…์‹ค/Spring Framework

728x90
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š”? ์ฃผ๋‹ˆํ•˜๋ž‘ ์ž…๋‹ˆ๋‹ค.

์˜ค๋Š˜์€ JPA์—  ๋Œ€ํ•ด ๊ณต๋ถ€ ํ•ด ๋ณด๋„๋ก ํ•  ๊ฒƒ์ด์—์š”.

๋ฐ”๋กœ ์‹œ์ž‘ ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

 

์ฝ”๋“œ์— ๊ด€๋ จํ•œ ๋‚ด์šฉ์€ ์ฃผ๋‹ˆํ•˜๋ž‘์˜ Github์—์„œ ํ™•์ธ ํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!





 

 

๐Ÿ“‹ ๋ชฉ์ฐจ


01.[Spring Boot] thymeleaf์™€ Spring Boot
02.[Spring Boot] Spring Web ๊ฐœ๋ฐœ ๊ธฐ์ดˆ
03.[Spring Boot] ํšŒ์› ๊ด€๋ฆฌ ์˜ˆ์ œ - Backend
04.[Spring Boot] Service ๊ฐœ๋ฐœ ๋ฐ Test Case ์ž‘์„ฑ
05.[Spring Boot] Spring Bean๊ณผ ์˜์กด๊ด€๊ณ„
06.[Spring Boot] Java Code๋กœ ์ง์ ‘ Spring Bean ๋“ฑ๋ก
07.[Spring Boot] ๋“ฑ๋ก, ๋ชฉ๋ก ๋ณด๊ธฐ ๊ตฌํ˜„ํ•˜๊ธฐ
08.[Spring Boot] ๊ธฐ์กด ์ฝ”๋“œ ์† ์•ˆ๋Œ€๊ณ , ์„ค์ •์œผ๋กœ ๊ตฌํ˜„ Class ๋ณ€๊ฒฝ
09.[Spring Boot] ํ†ตํ•ฉ Test
10.[Spring Boot] JPA
11.[Spring Boot] Spring Data JPA
12.[Spring Boot] AOP

 

 


 

 

 

 

๐Ÿ“Œ Java Code๋กœ ์ง์ ‘ Spring Bean ๋“ฑ๋ก


JPA๋Š” ๊ธฐ์กด์˜ ๋ฐ˜๋ณต Code๋Š” ๋ฌผ๋ก ์ด๊ณ , ๊ธฐ๋ณธ์ ์ธ SQL๋„ JPA๊ฐ€ ์ง์ ‘ ๋งŒ๋“ค์–ด์„œ ์‹คํ–‰์„ ํ•ด ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœ์ž๊ฐ€ Code์— SQL๋ฌธ์„ ์ž‘์„ฑํ•  ์ผ์ด ์ ์–ด์ง€๋Š” ๊ฒƒ์ด ํŠน์ง•์ธ ๊ฒƒ์ด์—์š”.

JPA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด SQL๊ณผ Data ์ค‘์‹ฌ์˜ ์„ค๊ณ„์—์„œ ๊ฐ์ฒด ์ค‘์‹ฌ์˜ ์„ค๊ณ„๋กœ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์—์š”. ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์„ ํฌ๊ฒŒ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ต๋‹ˆ๋‹ค!

 

JPA๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ด์ค˜์•ผ ํ•˜๋Š” ๊ฒƒ์ด์—์š”.

 

 

build.gradle

plugins {
	id 'org.springframework.boot' version '2.5.3'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '2.4.1'
	testImplementation('org.springframework.boot:spring-boot-starter-test') {
		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
}

test {
	useJUnitPlatform()
}

dependencis์— implementation์œผ๋กœ starter-data-jpa๋ฅผ ์ถ”๊ฐ€ ํ•ด ์ค€ ๊ฒƒ์ด์—์š”.
์ด ์˜์กด์„ฑ์—๋Š” jdbc ๊ด€๋ จ Library๋„ ํฌํ•จ ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— starter-jdbc๋Š” ์ง€์›Œ๋„ ์ƒ๊ด€ ์—†์ง€๋งŒ, ์ฃผ๋‹ˆํ•˜๋ž‘์€ ๊ทธ๋Œ€๋กœ ๋‚ฉ๋‘” ๊ฒƒ์ด์—์š”.

๊ทธ ๋ฐ‘์— ์žˆ๋Š” ๋‚ด์šฉ์€ mariaDB๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•œ ๊ฒƒ์ด๋ž๋‹ˆ๋‹ค!

 

         ๐Ÿ‘‰ Spring Boot JPA Config Insert

resources/application.properties

spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://[dbms_ip&port]/SpringStudy?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true
spring.datasource.username=junyharang
spring.datasource.password=ํŒจ์Šค์›Œ๋“œ
spring.jackson.property-naming-strategy=SNAKE_CASE
spring.jpa.show_sql = true
spring.jap.hibernate.ddl-auto=none
โš ๏ธ ์ฃผ์˜
Spring Boot 2.4๋ถ€ํ„ฐ๋Š” spring.datasource.username='DB ID' ๋“ฑ๊ณผ ๊ฐ™์ด DB ์ ‘์† ์ •๋ณด๋ฅผ ์ž…๋ ฅ ํ•ด์•ผ ํ•œ๋‹ค.

 

show-sql : JPA๊ฐ€ ์ƒ์„ฑํ•˜๋Š” SQL๋ฌธ ์ถœ๋ ฅ

ddl-auto : JPA๋Š” Table์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š”๋ฐ, none์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ฒŒ ๋œ๋‹ค.
               none์ด ์•„๋‹Œ create๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Entity ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ Table๋„ ์ง์ ‘ ์ƒ์„ฑ

 

 

    ๐Ÿ“ JPA Entity Mapping

Member.java

package hello.hellospring.domain;

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

@Entity
public class Member {

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

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
} // Class ๋

 

         ๐Ÿ‘‰ JPA Primary Key Mapping ์ „๋žต

JPA์—๋Š” ๊ธฐ๋ณธ ํ‚ค ๋งคํ•‘ ์ „๋žต์ด ํฌ๊ฒŒ 4๊ฐ€์ง€๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ด์—์š”.

  • ์ง์ ‘ ํ• ๋‹น : ๊ธฐ๋ณธ ํ‚ค๋ฅผ Application์—์„œ ์ง์ ‘ Entity Class์˜ @Id ํ•„๋“œ์— set
                      @Id๋งŒ ์‚ฌ์šฉ
  • ์ž๋™ ์ƒ์„ฑ : ๋Œ€๋ฆฌํ‚ค ์‚ฌ์šฉ ๋ฐฉ์‹
                      @Id ์™€ @GeneratedValue ๊ฐ™์ด ์‚ฌ์šฉ
    • IDENTITY : ๊ธฐ๋ณธ ํ‚ค ์ƒ์„ฑ์„ DB์— ์œ„์ž„ (์˜ˆ : MySQL, PostgreSQL, Server DB2 ๋“ฑ - Auto_Increment ๋“ฑ)
      • @GeneratedValue(strategy = GenerationType.IDENTITY)
      • id ๊ฐ’์„ null๋กœ Query๋ฅผ ๋‚ ๋ฆฌ๋ฉด DB๊ฐ€ ์•Œ์•„์„œ Auto_Increment๋ฅผ ์ž‘๋™
        • Auto_Increment๋Š” DB์— INSERT SQL Query๊ฐ€ ์‹คํ–‰๋œ ๋’ค id ๊ฐ’์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
        • id ๊ฐ’์€ DB์— ๊ฐ’์ด ๋“ค์–ด๊ฐ„ ๋’ค์—์•ผ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
        • ๋ฌธ์ œ์ : id ๊ฐ’์ด DB์— ๋“ค์–ด๊ฐ„ ๋’ค์— ์•Œ๊ฒŒ ๋œ๋‹ค๋ฉด?
          • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์—์„œ ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ๊ด€๋ฆฌ๋˜๋ ค๋ฉด ๋ฌด์กฐ๊ฑด Primary Key ๊ฐ’์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.
            ์ด ๊ฒฝ์šฐ Primary Key ๊ฐ’์€ DB์— ๋“ค์–ด๊ฐ€๋ด์•ผ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
          • IDENTITY ์ „๋žต์˜ ๊ฒฝ์šฐ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์˜ 1์ฐจ Cache์•ˆ์— ์žˆ๋Š” @Id ๊ฐ’์€ DB์— ๋„ฃ๊ธฐ ์ „๊นŒ์ง€ Setting์ด ๋ถˆ๊ฐ€
            (JPA ์ž…์žฅ์—์„œ Map์˜ Key ๊ฐ’์ด ์—†์œผ๋‹Œ๊นŒ ํ•ด๋‹น ๊ฐ์ฒด์˜ ๊ฐ’์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ• ์—†์Œ)
        • ํ•ด๊ฒฐ์ฑ…
          • IDENTITY ์ „๋žต์—์„œ๋งŒ ์˜ˆ์™ธ์ ์œผ๋กœ entityManager.persist()๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ์‹œ์ ์— ๋ฐ”๋กœ DB์— INSERT Query๋ฅผ ๋‚ ๋ฆฌ๋Š” ๋ฐฉ๋ฒ•
            ๋‹ค๋ฅธ ์ „๋žต์—์„œ๋Š” ์ด๋ฏธ id ๊ฐ’์„ ์•Œ๊ณ  ์žˆ๊ธฐ์— commit gksms tlwjadp INSERT Query๋ฅผ ๋‚ ๋ฆฐ๋‹ค.
          • ์œ„ ๊ณผ์ •์„ ํ†ตํ•ด entityManager.persist()๊ฐ€ ํ˜ธ์ถœ๋˜์ž๋งˆ์ž INSERT Query๋ฅผ ํ†ตํ•ด DB์—์„œ ์‹๋ณ„์ž๋ฅผ ์กฐํšŒํ•˜์—ฌ
            ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์˜ 1์ฐจ Cache ๊ฐ’์„ ๋„ฃ๋Š”๋‹ค. (SELECT ๋ฌธ์„ ๋‹ค์‹œ ๋‚ ๋ฆฌ์ง€ ์•Š์•„๋„ ๋˜๋Š” ์žฅ์ )
        • ๋‹จ์ : ํ•œ๊บผ๋ฒˆ์— ๋ชจ์€ ๋’ค INSERT ํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€
          • ์ด ๊ฒฝ์šฐ ๋ฒ„ํผ๋ง์„ ํ•ด์„œ Write๋ฅผ ํ•˜๋Š” ๊ฒƒ์ด ํฐ ์žฅ์ ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ํฌ๊ฒŒ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์•„๋„ ๋จ.
          • ํ•˜๋‚˜์˜ Transaction ์•ˆ์—์„œ ์—ฌ๋Ÿฌ INSERT Query๊ฐ€ Network๋ฅผ ํƒ„๋‹ค๊ณ  ํ•ด์„œ ์—„์ฒญ๋‚˜๊ฒŒ ์„ฑ๋Šฅ์ด ์ข‹์•„์ง€์ง€ ์•Š์Œ
      • // H2
        crate table Member (
        	id varchar(255) generated by default as identity,
            ...
        )
        
        // MySQL
        create table Member (
        	id varchar(255) auto_increment,
            ...
        )โ€‹
      • IDENTITY ์ „๋žต์€ entityManager.persist() ์‹œ์ ์— ์ฆ‰์‹œ INSERT SQL Query๋ฅผ ์‹คํ–‰ํ•˜๊ณ , DB ์‹๋ณ„์ž ์กฐํšŒ
        • JPA๋Š” ๋ณดํ†ต Transation commit ์‹œ์ ์— INSERT SQL Query ์‹คํ–‰
          • IDENTITY ์ „ 
    • SEQUENCE : DB SEQUNCE๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋ณธ ํ‚ค ํ• ๋‹น (์˜ˆ - Oracle sequence ๋“ฑ)
    • TABLE : ํ‚ค ์ƒ์„ฑ Table ์‚ฌ์šฉ (์˜ˆ : Sequnce์„ ์‚ฌ์šฉํ•˜๋Š” Table์„ ์‚ฌ์šฉํ•˜์—ฌ Table์˜ ๊ธฐ๋ณธํ‚ค ์ €์žฅ ๋ฐ ๊ด€๋ฆฌ

 

    ๐Ÿ“ Entity Manager

EntityManger๋Š” Entity๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๋Š” Class์ธ ๊ฒƒ์ด์—์š”.

EntityManger๋Š” ๋‚ด๋ถ€์— ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ(Persistence Context)๋ผ๋Š” ๊ฑธ ๋‘์–ด ๊ด€๋ฆฌ ํ•œ๋‹ต๋‹ˆ๋‹ค!

 

         ๐Ÿ‘‰ Persistence Context(์˜์†์„ฑ ์ปจํ…์ŠคํŠธ)๋ž€?

 

์˜์†์„ฑ์ด๋ž€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ปดํ“จํ„ฐ ๊ณตํ•™์—์„œ ์ด์•ผ๊ธฐํ•˜๋Š” ์˜์†์„ฑ์ธ๋ฐ, ์ด๊ฒƒ์€ ๋น„ ํœ˜๋ฐœ์„ฑ์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์—์š”.

ํœ˜๋ฐœ์„ฑ์€ ์ปดํ“จํ„ฐ์˜ ์ „์›์ด ๋‚˜๊ฐ€๋ฉด Data๊ฐ€ ๋ชจ๋‘ ๋‚ ์•„์ง€๋งŒ, ๋น„ ํœ˜๋ฐœ์„ฑ์€ ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒƒ์ด์ง€์š”.

์ด๋Ÿฐ ํœ˜๋ฐœ์„ฑ, ๋น„ ํœ˜๋ฐœ์„ฑ์ด๋ž€ ๋‹จ์–ด๋Š” ์ €์žฅ ์žฅ์น˜ (Memory ๋“ฑ)์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์šฉ์–ด์ด๊ณ , DB์—์„œ๋Š” ์˜์†์„ฑ์ด๋ผ๋Š” ๋‹จ์–ด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ต๋‹ˆ๋‹ค!

 

๊ฒฐ๊ตญ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋Š” Entity๋ฅผ ์˜๊ตฌํžˆ ์ €์žฅํ•˜๋Š” ํ™˜๊ฒฝ์ด๋ผ๊ณ  ๋ณด๋ฉด ๋˜๋Š” ๊ฒƒ์ด์—์š”.

 

JPA๋Š” Entity Manager์™€ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ํ†ตํ•ด Data์˜ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜๊ณ , ํ•„์š”ํ•œ Query๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด์—์š”.

 

mybatis์ฒ˜๋Ÿผ ์ง์ ‘ SQL Query๋ฅผ ์ž‘์„ฑํ•˜๊ฑฐ๋‚˜, JPA๋ฅผ ํ™œ์šฉํ•œ ๊ฐœ๋ฐœ์€ ๋ˆˆ์— ๋ณด์ด๋Š” ๊ฒƒ ์ด์ƒ์˜ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ต๋‹ˆ๋‹ค!

 

๊ทธ ์˜ˆ๋กœ CRUD๋กœ ๋ถˆ๋ฆฌ๋Š” ๊ธฐ๋ณธ์  4๊ฐ€์ง€ ๋™์ž‘ ์ค‘ UPDATE๋Š” JPA์— ์กด์žฌํ•˜์ง€ ์•Š์€ ๊ฒƒ์ด์—์š”.

ํ•˜์ง€๋งŒ, JPA๋Š” Update๋ฅผ ์ž˜ ๋™์ž‘ ์‹œํ‚จ๋‹ต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๊ฐ€ Data์˜ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•˜์—ฌ ์ž๋™์œผ๋กœ Update Query๋ฅผ ๋‚ ๋ ค์ฃผ๊ธฐ ๋•Œ๋ฌธ์ด์—์š”.

 

 

         ๐Ÿ‘‰ JPA ํšŒ์› Repository

JpaMemberRepository.java

package hello.hellospring.repository;

import hello.hellospring.domain.Member;

import javax.persistence.EntityManager;
import java.util.List;
import java.util.Optional;

public class JpaMemberRepository implements MemberRepository{

    private final EntityManager em;

    public JpaMemberRepository(EntityManager em) {
        this.em = em;
    } // JpaMemberRepository() ๋

    @Override
    public Member save(Member member) {
        em.persist(member);
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        Member member = em.find(Member.class, id);
        return Optional.ofNullable(member);
    }

    @Override
    public Optional<Member> findByName(String name) {
        List<Member> reulst = em.createQuery("select m from Member m where m.name = :name", Member.class).setParameter("name", name).getResultList();
        return reulst.stream().findAny();
    }

    @Override
    public List<Member> findAll() {
//        List<Member> result = em.createQuery("select m from Member m", Member.class).getResultList();
//        return result;

        // ์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋‹จ์ˆœํ™” ํ•œ ๊ฒƒ
        return em.createQuery("select m from Member m", Member.class).getResultList();
    }
}

 

 

 

         ๐Ÿ‘‰ Service Layer Taransational Insert

MemberService.java

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

// ์ปดํฌ๋„ŒํŠธ ์Šค์บ” ๋ฐฉ์‹์˜ Service
//@Service
@Transactional
public class MemberService {   // Service ์ชฝ์€ ๋น„์ฆˆ๋‹ˆ์Šค ์šฉ์–ด์— ๋งž๊ฒŒ ์ด๋ฆ„ ๋“ฑ์„ ์ ์–ด์•ผ ํ•œ๋‹ค.
        // ์•„๋ž˜ ๋‚ด์šฉ์—์„œ repository ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , Service Test์—์„œ ๋˜ new๋ฅผ ํ†ตํ•ด Repository๋ฅผ ์ƒ์„ฑํ•ด์„œ ํ…Œ์ŠคํŠธํ•˜๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•˜๊ฒŒ ๋œ๋‹ค.
//  private final MemoryMemberRepository memberRepository = new MemoryMemberRepository();

    // ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด ์ค€๋‹ค.
    private final MemberRepository memberRepository;

    // @Service๊ฐ€ ์žˆ๋Š” Service๊ฐ€ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ, @Autowired๊ฐ€ ๋ถ™์€ ์ƒ์„ฑ์ž๋Š” ์Šคํ”„๋ง์ด ์ปจํ…Œ์ด๋„ˆ์—์„œ ๋นˆ์œผ๋กœ ๊ด€๋ฆฌํ•  ๋•Œ, ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•˜๋Š”๋ฐ, ์ด ๋•Œ MemberService๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.
//    @Autowired
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    } // ์ƒ์„ฑ์ž ๋

    // ํšŒ์› ๊ฐ€์ž…
    public Long join(Member member) {
        // ๊ฐ™์€ ์ด๋ฆ„์ด ์žˆ๋Š” ์ค‘๋ณต ํšŒ์› ๊ฐ€์ž… ๋ฐฉ์ง€
//        Optional<Member> result = memberRepository.findByName(member.getName());
//
//        result.ifPresent(memeber -> { // ifPresent๋Š” ํ•ด๋‹น ๊ฐ’์ด Null์ด ์•„๋‹ˆ๊ณ , ์–ด๋–ค ๊ฐ’์ด ์žˆ์œผ๋ฉด ๋™์ž‘ (Option๋กœ ๊ฐ์‹ธ๋ฉด ์‚ฌ์šฉ ๊ฐ€๋Šฅ)
//            throw new IllegalStateException("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์› ์ž…๋‹ˆ๋‹ค.");
//        });

        // ์œ„์— ์ฝ”๋“œ ๋ณด๋‹ค ๋” ์ข‹์€ ์ฝ”๋“œ
//        memberRepository.findByName(member.getName()).ifPresent(member1 -> {
//            throw new IllegalStateException("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์› ์ž…๋‹ˆ๋‹ค.")
//        });

        // ์œ„์˜ ์ฝ”๋“œ๋ฅผ Methodํ™” ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
        // ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ๋ชจ๋‘ ์„ ํƒํ•˜๊ณ , Command + Option + M์„ ๋ˆŒ๋Ÿฌ์ค€๋‹ค.

        validateDuplicationMember(member);      // ์ค‘๋ณต ํšŒ์› ๊ฒ€์ฆ

        memberRepository.save(member);
        return member.getId();
    } // join() ๋

    private void validateDuplicationMember(Member member) {
        // ์œ„์— ์ฝ”๋“œ ๋ณด๋‹ค ๋” ์ข‹์€ ์ฝ”๋“œ
        memberRepository.findByName(member.getName()).ifPresent(member1 -> {
            throw new IllegalStateException("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์› ์ž…๋‹ˆ๋‹ค.");
        });
    } // validateDuplicationMember() ๋

    public List<Member> findMembers() {
        return memberRepository.findAll();
    } // findMembers() ๋

    public Optional<Member> findOne(Long memberId) {
        return memberRepository.findById(memberId);
    } // findOne() ๋

} // Class ๋

@Transational์€ org.springframework.transaction.annotation.Transactional๋ฅผ Importํ•˜๋ฉด ๋˜๋Š” ๊ฒƒ์ด์—์š”.

Spring์€ ํ•ด๋‹น Class์˜ Method๋ฅผ ์‹คํ–‰ํ•  ๋•Œ, Tansation์„ ์‹œ์ž‘ํ•˜๊ณ , Method๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด Transation์„ Commitํ•˜๋Š” ๊ฒƒ์ด์—์š”.

๋งŒ์•ฝ Run Time Error๊ฐ€ ๋‚œ๋‹ค๋ฉด? Roll Back์„ ํ•œ๋‹ต๋‹ˆ๋‹ค!

JPA๋ฅผ ํ†ตํ•œ ๋ชจ๋“  Data ๋ณ€๊ฒฝ์€ Transation์•ˆ์—์„œ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์  ๊ธฐ์–ตํ•ด์•ผ ๋˜๋Š” ๊ฒƒ์ด์—์š”!

 

 

         ๐Ÿ‘‰ JPA๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก Spring Config Modifie

SpringConfig.java

package hello.hellospring;

import hello.hellospring.repository.JdbcMemberRepository;
import hello.hellospring.repository.JdbcTemplateMemberRepository;
import hello.hellospring.repository.JpaMemberRepository;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.persistence.EntityManager;
import javax.sql.DataSource;

@Configuration
public class SpringConfig {

    private DataSource source;
    private EntityManager em;

    @Autowired
    public SpringConfig(DataSource source, EntityManager em) {
        this.source = source;
        this.em = em;
    } // ์ƒ์„ฑ์ž ๋

    // @Bean : Bean์„ ๋‚ด๊ฐ€ ์ง์ ‘ ๋งŒ๋“ค๊ฒ ๋‹ค๋Š” ์˜๋ฏธ; ์Šคํ”„๋ง์€ ์ด๊ฒƒ์„ ๋ณด๊ณ , Bean์„ ๋“ฑ๋กํ•˜๋ผ๋Š” ๋ช…๋ น์œผ๋กœ ์ธ์‹
    @Bean
    // ์•„๋ž˜ Method๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Bean์— ๋“ฑ๋ก
    public MemberService memberService() {
        // MeberService๋ฅผ ์ƒ์„ฑํ•˜๋ฉด์„œ memberRepository๋ฅผ Spring Bean์— ๋“ฑ๋ก ๋œ ์ฃผ์ž…ํ•˜์—ฌ ์ค€๋‹ค.
        return new MemberService(memberRepository());
    } // memberService() ๋

    @Bean
    public MemberRepository memberRepository() {
//        return new MemoryMemberRepository();
//        return new JdbcMemberRepository(source);
//        return new JdbcTemplateMemberRepository(source);
        return new JpaMemberRepository(em);
    } // memberRepository() ๋
} // Class ๋

 

 

 


 

์ฃผ๋‹ˆํ•˜๋ž‘์˜ ๊ธ€์ด ๋งˆ์Œ์— ๋“œ์…จ๋‚˜์š”? ๊ตฌ๋…๊ณผ ๊ณต๊ฐ! ๊ทธ๋ฆฌ๊ณ , ๋Œ“๊ธ€์€ ์ฃผ๋‹ˆํ•˜๋ž‘์—๊ฒŒ ๋งŽ์€ ํž˜์ด ๋ฉ๋‹ˆ๋‹ค

728x90
๋ฐ˜์‘ํ˜•