# Spring ์ž…๋ฌธ / 6. DB ์ ‘๊ทผ ๊ธฐ์ˆ 
Study Repository

Spring ์ž…๋ฌธ / 6. DB ์ ‘๊ทผ ๊ธฐ์ˆ 

by rlaehddnd0422

1.  H2 DB ์„ค์น˜

H2 DB๋Š” ๊ฐœ๋ฐœ์ด๋‚˜ ํ…Œ์ŠคํŠธ ์šฉ๋„๋กœ ๊ฐ€๋ณ๊ณ  ํŽธ๋ฆฌํ•œ DB, ์›น ํ™”๋ฉด์„ ์ œ๊ณต

 

ํ…Œ์ด๋ธ” ์ƒ์„ฑ

drop table if exists member CASCADE;
    create table member
    (
        id   bigint generated by default as identity,
        name varchar(255),
        primary key (id)
);

2.  ์ˆœ์ˆ˜ JDBC

 

ํ™˜๊ฒฝ์„ค์ •

build.gradle ํŒŒ์ผ์— jdbc, h2 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€

implementation 'org.springframework.boot:spring-boot-starter-jdbc'
runtimeOnly 'com.h2database:h2'

 

์Šคํ”„๋ง ๋ถ€ํŠธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์„ค์ • ์ถ”๊ฐ€

   resources/application.properties
     spring.datasource.url=jdbc:h2:tcp://localhost/~/test
     spring.datasource.driver-class-name=org.h2.Driver
     spring.datasource.username=sa

 

Jdbc ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๊ตฌํ˜„

package kdo6301.spring0.repository;

import kdo6301.spring0.domain.Member;
import kdo6301.spring0.repository.MemberRepository;
import org.springframework.jdbc.datasource.DataSourceUtils;
import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class JdbcMemberRepository implements MemberRepository {
    private final DataSource dataSource;

    public JdbcMemberRepository(DataSource dataSource) {
        this.dataSource = dataSource;

    }
    @Override
    public Member save(Member member) {
        String sql = "insert into member(name) values(?)";

        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql,
                    Statement.RETURN_GENERATED_KEYS);
            pstmt.setString(1, member.getName());
            pstmt.executeUpdate();
            rs = pstmt.getGeneratedKeys();
            if (rs.next()) {
                member.setId(rs.getLong(1));
            } else {
                throw new SQLException("id ์กฐํšŒ ์‹คํŒจ");
            }
            return member;
        } catch (Exception e) {
            throw new IllegalStateException(e);
        } finally {
            close(conn, pstmt, rs);
        }
    }
    @Override
    public Optional<Member> findById(Long id) {
        String sql = "select * from member where id = ?";
        Connection conn = null;
        PreparedStatement pstmt = null;

        ResultSet rs = null;
        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setLong(1, id);
            rs = pstmt.executeQuery();
            if(rs.next()) {
                Member member = new Member();
                member.setId(rs.getLong("id"));
                member.setName(rs.getString("name"));
                return Optional.of(member);
            } else {
                return Optional.empty();
            }
        } catch (Exception e) {
            throw new IllegalStateException(e);
        } finally {
            close(conn, pstmt, rs);
        } }
    @Override
    public List<Member> findAll() {
        String sql = "select * from member";
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);
            rs = pstmt.executeQuery();

            List<Member> members = new ArrayList<>();
            while(rs.next()) {
                Member member = new Member();
                member.setId(rs.getLong("id"));
                member.setName(rs.getString("name"));
                members.add(member);
            }
            return members;
        } catch (Exception e) {
            throw new IllegalStateException(e);
        } finally {
            close(conn, pstmt, rs);
        }
    }
    @Override
    public Optional<Member> findByName(String name) {
        String sql = "select * from member where name = ?";
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, name);
            rs = pstmt.executeQuery();
            if(rs.next()) {
                Member member = new Member();
                member.setId(rs.getLong("id"));
                member.setName(rs.getString("name"));
                return Optional.of(member);
            }

            return Optional.empty();
        } catch (Exception e) {
            throw new IllegalStateException(e);
        } finally {
            close(conn, pstmt, rs);
        }
    }
    private Connection getConnection() {
        return DataSourceUtils.getConnection(dataSource);
    }
    private void close(Connection conn, PreparedStatement pstmt, ResultSet rs)
    {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } try {
        if (pstmt != null) {
            pstmt.close();
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
        try {
            if (conn != null) {
                close(conn);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } }
    private void close(Connection conn) throws SQLException {
        DataSourceUtils.releaseConnection(conn, dataSource);

    }
}
  • DataSource๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜์„ ํš๋“ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด.
  • SpringBoot๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ DataSource๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋งŒ๋“ค์–ด๋‘”๋‹ค. ๊ทธ๋ž˜์„œ DI๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™(OCP, Open-Closed Principle) ํ™•์žฅ์—๋Š” ์—ด๋ ค์žˆ๊ณ , ์ˆ˜์ •, ๋ณ€๊ฒฝ์—๋Š” ๋‹ซํ˜€์žˆ๋‹ค.

    ์Šคํ”„๋ง์˜ DI (Dependencies Injection)์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์ „ํ˜€ ์†๋Œ€์ง€ ์•Š๊ณ , ์„ค์ •๋งŒ์œผ๋กœ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

    ํšŒ์›์„ ๋“ฑ๋กํ•˜๊ณ  DB์— ๊ฒฐ๊ณผ๊ฐ€ ์ž˜ ์ž…๋ ฅ๋˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ DB์— ์ €์žฅํ•˜๋ฏ€๋กœ ์Šคํ”„๋ง ์„œ๋ฒ„๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•ด๋„ ๋ฐ์ดํ„ฐ๊ฐ€ ์•ˆ์ „ํ•˜๊ฒŒ ์ €์žฅ๋œ๋‹ค.

     


    ๊ทธ ์™ธ์˜ ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ์žฅํ™ฉํ•˜๊ณ  ์˜ฌ๋“œํ•œ ๋ฐฉ์‹์ด๋ผ ์ฝ”๋“œ์— ๋Œ€ํ•œ ์„ค๋ช… ์ƒ๋žต. ์ด๋ ‡๊ฒŒ ์งฐ๋‹ค ์ฐธ๊ณ ๋งŒ ํ•˜๊ณ  ๋„˜์–ด๊ฐ

3.  ์Šคํ”„๋ง ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ

package kdo6301.spring0.service;

import kdo6301.spring0.domain.Member;
import kdo6301.spring0.repository.MemberRepository;
import kdo6301.spring0.repository.MemoryMemberRepository;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
@Transactional
class MemberServiceIntegrationTest {
    @Autowired MemberService memberService;
    @Autowired MemberRepository memberRepository;

    @Test
    void join()
    {
        //given
        Member member = new Member();
        member.setName("Kim");
        //when
        Long saveId = memberService.join(member);

        //then
        Member One = memberService.findOne(saveId).get();
        Assertions.assertThat(member.getName()).isEqualTo(One.getName());
    }
    @Test
    void ์ค‘๋ณตํšŒ์›์˜ˆ์™ธ()
    {
        // given
        Member mem1 = new Member();
        mem1.setName("Spring1");

        Member mem2 = new Member();
        mem2.setName("Spring1");

        // when

        memberService.join(mem1);
        IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(mem2));
        Assertions.assertThat(e.getMessage()).isEqualTo("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์›์ž…๋‹ˆ๋‹ค.");

//        try
//        {
//            memberService.join(mem2);
//            fail();
//        }catch(IllegalStateException e){
//            Assertions.assertThat(e.getMessage()).isEqualTo("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์›์ž…๋‹ˆ๋‹ค.");
//        }

        // then
    }

}

์•ž์„œ MemoryMemberRepository๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์—๋Š”, @BeforeEach๋‚˜ @AfterEach๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ๋Œ๋ฆด ๋•Œ ๋งˆ๋‹ค ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์ดˆ๊ธฐํ™” ํ•ด์ฃผ์–ด ๊ฐ ํ…Œ์ŠคํŠธ๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰ํ–ˆ์—ˆ๋‹ค.

 

+ ์šฐ๋ฆฌ๋Š” JDBC DB๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ–ˆ์œผ๋ฏ€๋กœ ๊ธฐ์กด์— ์žˆ๋˜ MemoryMemberRepository๊ฐ€ ์•„๋‹Œ MemberRepository๋กœ ๋ณ€๊ฒฝํ•˜์˜€๋‹ค.

 

@Transactional ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ํ…Œ์ŠคํŠธ ์ง„ํ–‰ ์ „์— ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•˜๊ณ , ํ…Œ์ŠคํŠธ ์™„๋ฃŒ ํ›„์—๋Š” ํ•ญ์ƒ ๋กค๋ฐฑ์„ ์ง„ํ–‰ํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด DB์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚จ์ง€ ์•Š์•„ ๋‹ค์Œ ํ…Œ์ŠคํŠธ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค.

 

@SpringBootTest๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ „์ฒด Bean์„ ๋ชจ๋‘ ๊ฐ€์ ธ์˜ค๊ณ , ํ…Œ์ŠคํŠธ๋ฅผ ํ•จ๊ป˜ ์ง„ํ–‰ํ•œ๋‹ค. ์‰ฝ๊ฒŒ ๋งํ•ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์™€ ํ…Œ์ŠคํŠธ๋ฅผ ํ•จ๊ป˜ ์‹คํ–‰ํ•œ๋‹ค. 

 

 

4. ์Šคํ”„๋ง JdbcTemplate

์ˆœ์ˆ˜ Jdbc์™€ ๋™์ผํ•œ ํ™˜๊ฒฝ์„ค์ •์„ ํ•˜๋ฉด ๋œ๋‹ค.
์Šคํ”„๋ง JdbcTemplate๊ณผ MyBatis ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” JDBC API์—์„œ ๋ณธ ๋ฐ˜๋ณต ์ฝ”๋“œ๋ฅผ ๋Œ€๋ถ€๋ถ„ ์ œ๊ฑฐํ•ด์ค€๋‹ค. ํ•˜์ง€๋งŒ SQL์€ ์ง์ ‘ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.

 

์Šคํ”„๋ง JdbcTemplate ํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ

package kdo6301.spring0.repository;

import kdo6301.spring0.domain.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;

import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class JdbcTemplateMemberRepository implements MemberRepository{

    private final JdbcTemplate jdbcTemplate;

    // ์ƒ์„ฑ์ž๊ฐ€ ํ•˜๋‚˜์ผ ๋•Œ ์ƒ๋žต ๊ฐ€๋Šฅ @Autowired
    public JdbcTemplateMemberRepository(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override
    public Member save(Member member) {
        SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
        jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");

        Map<String, Object> parameters = new HashMap<>();
        parameters.put("name", member.getName());
        Number key = jdbcInsert.executeAndReturnKey(new
                MapSqlParameterSource(parameters));
        member.setId(key.longValue());
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        List<Member> result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(),id);
        return result.stream().findAny();
    }

    @Override
    public Optional<Member> findByName(String name) {
        List<Member> result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name);
        return result.stream().findAny();
    }

    @Override
    public List<Member> findAll() {
        return jdbcTemplate.query("select * from member", memberRowMapper());
    }


    private RowMapper<Member> memberRowMapper()
    {
        return (rs, rowNum) -> {
            Member member = new Member();
            member.setId(rs.getLong("id"));
            member.setName(rs.getString("name"));
            return member;
        };
    }
}

0. memberRowMapper

- RowMapper๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์›ํ•˜๋Š” ํ˜•ํƒœ์˜ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

return (rs, rowNum) -> {
    Member member = new Member();
    member.setId(rs.getLong("id"));
    member.setName(rs.getString("name"));
    return member;
};

member๋ฅผ ์ƒ์„ฑํ•˜๊ณ  resultset rs๋กœ๋ถ€ํ„ฐ ์•„์ด๋””์™€ ์ด๋ฆ„์„ ๋ฐ›์•„์™€  member๊ฐ์ฒด์— ์ €์žฅํ•œ๋‹ค.

 

1. findByID , name, All

 

query์— ๋Œ€ํ•œ ๊ฒฐ๊ด๊ฐ’์„ memberRowMapper()์— ๋งคํ•‘ํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ ํ˜•ํƒœ๋กœ ๋ฆฌํ„ด

 

JdbcTemplate์„ ์‚ฌ์šฉํ•˜๋„๋ก ์Šคํ”„๋ง ์„ค์ • ๋ณ€๊ฒฝ

@Bean
      public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
        return new JdbcMemberRepository(dataSource);
          return new JdbcTemplateMemberRepository(dataSource);
      }

 

5.  JPA

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

 

 

JPA ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘

package kdo6301.spring0.domain;

import jdk.jfr.Name;

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 String getName() {
        return name;
    }

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

    public void setName(String name) {
        this.name = name;
    }

}

 

JPA ํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ

package kdo6301.spring0.repository;

import kdo6301.spring0.domain.Member;
import org.springframework.transaction.annotation.Transactional;

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;
    }

    @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> result = em.createQuery("select m from Member as m where m.name = :name",Member.class)
                .setParameter("name",name)
                .getResultList();

        return result.stream().findAny();
    }

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

    }
}

JPA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐœ๋ฐœ์ฝ”๋“œ๋“ค์ด ํ™•์—ฐํ•˜๊ฒŒ ์ค„์–ด๋“œ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

์„œ๋น„์Šค ๊ณ„์ธต์— ํŠธ๋žœ์žญ์…˜ ์ถ”๊ฐ€

import org.springframework.transaction.annotation.Transactional
  @Transactional
  public class MemberService {}

์Šคํ”„๋ง์€ ํ•ด๋‹น ํด๋ž˜์Šค์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•˜๊ณ  ๋ฉ”์†Œ๋“œ๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ํŠธ๋žœ์žญ์…˜์„ ์ปค๋ฐ‹ํ•œ๋‹ค.

JPA๋ฅผ ํ†ตํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์€ ํŠธ๋žœ์žญ์…˜ ์•ˆ์—์„œ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

 

๋นˆ ๊ณ„์ธต ๋ณ€๊ฒฝ

@Bean
        public MemberRepository memberRepository() {
         // return new MemoryMemberRepository();
         // return new JdbcMemberRepository(dataSource);
         // return new JdbcTemplateMemberRepository(dataSource);
            return new JpaMemberRepository(em);
        }

 

6. ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA

์Šคํ”„๋ง ๋ถ€ํŠธ์™€ JPA๋งŒ ์‚ฌ์šฉํ•ด๋„ ๊ฐœ๋ฐœ์ƒ์‚ฐ์„ฑ์ด ๋งŽ์ด ์ฆ๊ฐ€ํ–ˆ์ง€๋งŒ, ์—ฌ๊ธฐ์— ๋”๋ถˆ์–ด ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ์กด์˜ ํ•œ๊ณ„๋ฅผ ๋„˜์–ด ์ธํ„ฐํŽ˜์ด์Šค ๋งŒ์œผ๋กœ ๊ฐœ๋ฐœ์„ ์™„๋ฃŒํ•  ์ˆ˜ ์žˆ๋‹ค.

์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA๋Š” JPA๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋„๋ก ๋„์™€์ฃผ๋Š” ๊ธฐ์ˆ ๋กœ JPA๋ฅผ ๋จผ์ € ๋ฐฐ์šดํ›„์— ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA๋ฅผ ํ•™์Šตํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

 

์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA ํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ

package kdo6301.spring0.repository;

import kdo6301.spring0.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository{

    // JPQL - select m from Member as m where m.name = ?
    @Override
    Optional<Member> findByName(String name);
}

 

๋ฌธ๋ฒ• / interface๋Š” extends๋ฅผ ํ†ตํ•ด ๋‹ค์ค‘ ์ƒ์†์ด ๊ฐ€๋Šฅํ•˜๋‹ค. 

 

JpaRepository์—๋Š” findAll(), saveAll() ๋“ฑ๊ณผ ๊ฐ™์€ ๋ฉ”์†Œ๋“œ๋“ค์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ๋Š”๋ฐ ์ด ๊ธฐ๋ณธ ๋ฉ”์†Œ๋“œ์™ธ์˜ findByName, findById ๊ฐ™์€ ๋ฉ”์†Œ๋“œ๋“ค์€ ๋ฉ”์†Œ๋“œ ์ด๋ฆ„์„ ํ†ตํ•ด JPA๊ฐ€ JPQL๋ฌธ์„ ์ƒ์„ฑํ•˜์—ฌ ์ž๋™์ ์œผ๋กœ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜์—ฌ ์ œ๊ณตํ•ด์ค€๋‹ค !

 

- ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA ์ œ๊ณต ๊ธฐ๋Šฅ

  • JpaRepository์—๋Š” findByName() , findByEmail() ์ฒ˜๋Ÿผ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ํ†ตํ•œ ์กฐํšŒ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.
  • ํŽ˜์ด์ง• ๊ธฐ๋Šฅ ์ œ๊ณต
  • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•œ ๊ธฐ๋ณธ์ ์ธ CRUD

 

โ—๏ธ์ฐธ๊ณ 

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

์ด ์กฐํ•ฉ์œผ๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ ์–ด๋ ค์šด ์ฟผ๋ฆฌ๋Š” JPA๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ์•ž์„œ ํ•™์Šตํ•œ ์Šคํ”„๋ง JdbcTemplate๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

 

์Šคํ”„๋ง ๋นˆ์— ๋“ฑ๋ก

package kdo6301.spring0;

import kdo6301.spring0.repository.*;
import kdo6301.spring0.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {

    private final MemberRepository memberRepository;

    @Autowired
    public SpringConfig(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Bean
    public MemberService memberService()
    {
        return new MemberService(memberRepository);
    }

//    @Bean
//    public MemberRepository memberRepository()
//    {
////        return new JdbcMemberRepository(dataSource);
////        return new JdbcTemplateMemberRepository(dataSource);
////        return new JpaMemberRepository(em);
//
//    }

}

 

์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA๊ฐ€ SpringDataJpaMemberRepository๋ฅผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ์ž๋™ ๋“ฑ๋กํ•ด์ค€๋‹ค.

 

 

<์ •๋ฆฌ>

 

>   H2๋ฅผ ์„ค์น˜ํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์„ค์น˜ํ•˜์—ฌ ์ˆœ์ˆ˜ํ•œ jdbc ๊ธฐ์ˆ ๋กœ ์‚ฌ์šฉํ•ด ๋ดค๋”๋‹ˆ ๋ฉ”์†Œ๋“œ ํ•˜๋‚˜ํ•˜๋‚˜ ๊ตฌํ˜„ ํŒŒํŠธ๊ฐ€ ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€๊ณ  ์ฝ”๋“œ๊ฐ€ ์žฅํ™ฉํ•จ.

 

>   ํ†ตํ•ฉํ…Œ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์•˜์Œ

 

>  Jdbctemplate ๋ฅผ ์‚ฌ์šฉํ•ด๋ดค์ง€๋งŒ sql ์ง์ ‘ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์—ˆ์Œ

 

>  jpa๋Š” ๊ธฐ๋ณธ์ ์ธ crud(create, read, update, delete) ํ•˜๋Š”๋ฐ ์ฟผ๋ฆฌ ์ž‘์„ฑํ•  ํ•„์š” ์—†์—ˆ์Œ

 

> ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ jpa๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๋‹ˆ ์•„์˜ˆ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์ด ์ธํ„ฐํŽ˜์ด์Šค๋งŒ์œผ๋กœ ๊ฐœ๋ฐœ์„ ํ•  ์ˆ˜ ์žˆ์—ˆ์Œ

 

 

<์ฐธ๊ณ  ์ž๋ฃŒ>

 

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8/dashboard

 

[๋ฌด๋ฃŒ] ์Šคํ”„๋ง ์ž…๋ฌธ - ์ฝ”๋“œ๋กœ ๋ฐฐ์šฐ๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ, ์›น MVC, DB ์ ‘๊ทผ ๊ธฐ์ˆ  - ์ธํ”„๋Ÿฐ | ๊ฐ•์˜

์Šคํ”„๋ง ์ž…๋ฌธ์ž๊ฐ€ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€๋ฉด์„œ ์Šคํ”„๋ง ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ ์ „๋ฐ˜์„ ๋น ๋ฅด๊ฒŒ ํ•™์Šตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค., - ๊ฐ•์˜ ์†Œ๊ฐœ | ์ธํ”„๋Ÿฐ...

www.inflearn.com

 

https://atoz-develop.tistory.com/entry/H2-Database-%EC%84%A4%EC%B9%98-%EC%84%9C%EB%B2%84-%EC%8B%A4%ED%96%89-%EC%A0%91%EC%86%8D-%EB%B0%A9%EB%B2%95

 

H2 Database ์„ค์น˜, ์„œ๋ฒ„ ์‹คํ–‰, ์ ‘์† ๋ฐฉ๋ฒ• (Windows, MacOS)

H2 Database ์„ค์น˜, ์„œ๋ฒ„ ์‹คํ–‰, ์ ‘์† ๋ฐฉ๋ฒ• (Windows, MacOS) H2 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์„ค์น˜๊ฐ€ ํ•„์š” ์—†๊ณ  ์šฉ๋Ÿ‰์ด ๋งค์šฐ ๊ฐ€๋ฒผ์šฐ๋ฉฐ ์›น์šฉ ์ฝ˜์†”(์ฟผ๋ฆฌํˆด)์„ ์ œ๊ณตํ•˜์—ฌ ๊ฐœ๋ฐœ์šฉ ๋กœ์ปฌ DB๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๋‹ค. H

atoz-develop.tistory.com

https://mommoo.tistory.com/62

 

ํŠธ๋žœ์žญ์…˜(Transaction)์ด๋ž€?

ํŠธ๋žœ์žญ์…˜์ด๋ž€? ํŠธ๋žœ์žญ์…˜(Transaction ์ดํ•˜ ํŠธ๋žœ์žญ์…˜)์ด๋ž€, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ƒํƒœ๋ฅผ ๋ณ€ํ™”์‹œํ‚ค๊ธฐ ํ•ด์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์˜ ๋‹จ์œ„๋ฅผ ๋œปํ•œ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ƒํƒœ๋ฅผ ๋ณ€ํ™”์‹œํ‚จ๋‹ค๋Š” ๊ฒƒ์€ ๋ฌด์–ผ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ผ

mommoo.tistory.com

 

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

Study Repository

rlaehddnd0422

ํ™œ๋™ํ•˜๊ธฐ