스프링/0. 입문, 전체방향

16강. 순수 JDBC

sdafdq 2023. 7. 9. 16:00

옛날에 쓰던 방식.

build.gradle에 라이브러리를 추가 해야 함.

 

implementation 'org.springframework.boot:spring-boot-starter-jdbc'
runtimeOnly 'com.h2database:h2'
spring.datasource.username=sa
implementation 'org.springframework.boot:spring-boot-starter-jdbc'

기본적으로 java에서 db 쓸려면 저게 필요함.

 

runtimeOnly 'com.h2database:h2'

h2 db를 쓴다.

저거 해주고 gradle 새로고침 해줘야 적용됨. 아마 저 정보보고 웹에서 다운로드? 인듯.

 

spring.datasource.username=sa

이것도 써야 함. 

 

G:\spring\hello-spring\src\main\resources\application.properties

여기에다가 db 접속정보를 넣어줘야 함.

현재는 경로만 넣어주면 됨.

spring.datasource.url=jdbc:h2:tcp://localhost/~/test

전에 h2 접속할 때 경로.

 

spring.datasource.driver-class-name=org.h2.Driver

h2 쓴다고

 

이거 h2 접속해보면 연결하기 전에 다 써있음.

 

원래는 id, 비밀번호도 적고 하는데, h2에선 일단 생략.

 

 

 

public class JdbcMemberRepository implements MemberRepository{
    private final DataSource dataSource;  //db 쓸려면 dataSource 필요
    public JdbcMemberRepository(DataSource dataSource) {   //나중에 spring 에서부터 주입받도록
        this.dataSource = dataSource;
    }


    @Override
    public Member save(Member member) {
        String sql = "insert into member(name) values(?)";   //save 쿼리. 이거는 상수로 빼는게 낫긴 함. ?는 바인딩.

        Connection conn = null;     //커넥트 가져옴
        PreparedStatement pstmt = null;     //문장 작성
        ResultSet rs = null;    //이건 결과 받는 거

        try{    //얘네 예외 엄청 떠서 try catch 잘 해야 함.
            conn = getConnection();     //커넥션 얻어 오고
            pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);  //문장 작성

            pstmt.setString(1, member.getName());    //?에 삽입

            pstmt.executeUpdate();      // 쿼리 날리기
            rs = pstmt.getGeneratedKeys();   //RETURN_GENERATED_KEYS 반환

            if(rs.next()){  //next에 값이 있는지 검사. 처음이 0이 아니라 0 이전이라 next가 0번째임.
                member.setId(rs.getLong(1));
            } else{
                throw new SQLException("id 조회 실패");
            }
            return member;
        } catch (Exception e) {
            throw new IllegalStateException(e);
        } finally {
            close(conn, pstmt, rs); //DB 커넥션은 다 쓰면 바로 끊어 줘야 함. 아니면 계속 쌓이다가 참사가 일어날 수도..
        }
    }

    @Override
    public Optional<Member> findById(Long id) {
        String sql = "select * from member where id = ?";   //save 쿼리. 이거는 상수로 빼는게 낫긴 함.

        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;    //이건 결과 받는 거

        try{
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setLong(1,id);

            rs = pstmt.executeQuery();  //삽입이 아닌 조회는 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 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);
            } 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);
        }
    }


    private Connection getConnection(){
        return DataSourceUtils.getConnection(dataSource);   //스프링에서 DB 커넥션을 쓸거면 DataSourceUtils를 통해 획득 해야 한다.
    }

    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);    //닫을 때도 스프링에서는 releaseConnection를 통해 닫아야 함.
    }
}

이거 고전버전.

 

 

@Configuration
public class SpringConfig {
    private DataSource dataSource;

    @Autowired
    public SpringConfig(DataSource dataSource){
        this.dataSource = dataSource;
    }
    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

//    @Bean
//    public MemberRepository memberRepository(){
//        return new MemoryMemberRepository();
//    }

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

SpringConfig.java임.

저렇게 기존 MemberRepopsitory에서 Jdbc로 바꿔 끼워주면 됨.

참고로, 

   @Autowired
    public SpringConfig(DataSource dataSource){
        this.dataSource = dataSource;
    }

이거 같은 경우, @Autowired 해주면,

알아서 스프링이

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

application.properties에서 DataSource 찾아서 넣어줌.

'스프링 > 0. 입문, 전체방향' 카테고리의 다른 글

18강. Jdbc 템플릿  (0) 2023.07.09
17강. spring 종합 테스트  (0) 2023.07.09
15강. H2 DB  (0) 2023.07.08
14강. 간단한 웹 기능 -조회  (0) 2023.07.08
13강. 간단 회원 웹 기능 -등록  (0) 2023.07.08