๐ŸŒฑSpring H2 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค์น˜์™€ ์ˆœ์ˆ˜ JDBC

์ธํ”„๋Ÿฐ ์Šคํ”„๋ง ์ž…๋ฌธ ๊ฐ•์˜๋ฅผ ๋ณด๊ณ  ์Šคํ”„๋ง์„ ๊ณต๋ถ€ ํ›„ ๊ธฐ๋ก์šฉ์œผ๋กœ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค

1. H2 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค์น˜

h2๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค ๋ฒ„์ „์€ ๊ฐ•์˜์— ๋‚˜์˜จ๋Œ€๋กœ 1.4.200 ๋ฒ„์ „์œผ๋กœ ๋‹ค์šด ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค ๊ทธ๋’ค๋กœ ์Šคํ”„๋ง ํ”„๋กœ์ ํŠธ๊ฐ€ ์žˆ๋Š” Spring_std์— ์••์ถ•์„ ํ•ด์ œ ํ–ˆ์Šต๋‹ˆ๋‹ค

C:\Spring_std\H2\bin>h2.bat

cmd์ฐฝ์—์„œ h2๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค
์œˆ๋„์šฐ๋Š” h2.bat ์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค

์‹คํ–‰ํ•˜๋ฉด ์ž๋™์œผ๋กœ ์›น๋ธŒ๋ผ์šฐ์ € ํŽ˜์ด์ง€๊ฐ€ ๋‚˜์˜ต๋‹ˆ๋‹ค
ํ˜„์žฌ ์ƒํƒœ๋กœ ์ตœ์ดˆ๋กœ ์—ฐ๊ฒฐ ํ•ด์ค๋‹ˆ๋‹ค

์ƒ๋‹จ ์™ผ์ชฝ์— ์žˆ๋Š” ๋นจ๊ฐ„ ์  ๋‘๊ฐœ๋กœ ๋‹ค์‹œ ์ฒ˜์Œ ํ™”๋ฉด์œผ๋กœ ๋Œ์•„์™€


JDBC URL : ์ด๋ถ€๋ถ„์— ์•„๋ž˜์™€ ๊ฐ™์ด ์ž…๋ ฅํ•˜์—ฌ

jdbc:h2:tcp://localhost/~/test

๋‹ค์‹œ ํ•œ๋ฒˆ ์—ฐ๊ฒฐํ•ด์ค๋‹ˆ๋‹ค
๊ทธ๋Ÿฌ๋ฉด ๋””๋น„ ์—ฐ๊ฒฐ์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค

member ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑ ํ–ˆ์Šต๋‹ˆ๋‹ค

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

๊ฐ’์„ ๋„ฃ๊ธฐ ์œ„ํ•ด insert ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ ธ์Šต๋‹ˆ๋‹ค

insert into member(name) values('spring')

์œ„ ๊ฒฐ๊ณผ๋Œ€๋กœ ๋””๋น„์— ์ž˜ ๋“ค์–ด๊ฐ„๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค

2. ์ˆœ์ˆ˜ JDBC

spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa //์ถ”๊ฐ€
spring.datasource.password= //์ถ”๊ฐ€

์ฒ˜์Œ์—” ์ฝ”๋“œ๊ฐ€ ๋‘์ค„์ด์˜€๋Š”๋ฐ ์˜ค๋ฅ˜๊ฐ€ ๋‚ฌ๋”๋‹ˆ
์œ ์ €๋„ค์ž„๊ณผ ํŒจ์Šค์›Œ๋“œ๊นŒ์ง€ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋œ๋‹ค๋Š” ์ต๋ช…๋‹˜ ๋„์›€!
์ถ”๊ฐ€ํ–ˆ๋”๋‹ˆ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜์ง€ ์•Š๊ณ  ์ž˜ ์‹คํ–‰์ด๋ฉ๋‹ˆ๋‹ค

JdbcMemberRepository

package hello.hellospring.repository;
import hello.hellospring.domain.Member;
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);
    }
}

SpringConfig

import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class SpringConfig {

    @Autowired
    DataSource dataSource;

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

์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•œ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค

@Autowired
    DataSource dataSource;
 return new JdbcMemberRepository(dataSource); 

MemberRepository ์ƒ์„ฑ์ž ํ˜ธ์ถœ ํ•  ๋•Œ JdbcMemberRepository ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ–ˆ์Šต๋‹ˆ๋‹ค

ํšŒ์›๋ชฉ๋ก์— ๋“ค์–ด๊ฐ€๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ์ž˜๋‚˜์˜ต๋‹ˆ๋‹ค

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


์˜›๋‚  ๊ฐœ๋ฐœ์ž๋ถ„๋“ค์€ ์ผ์ผ์ด ์ฝ”๋”ฉํ•˜๋Š๋ผ ํž˜๋“ค์–ด๊ฒ ๋‹ค... ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค ์Šคํ”„๋ง์— ์ข€ ๋” ๊ฐ€๊นŒ์›Œ์กŒ์Šต๋‹ˆ๋‹ค ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ