[스프링] 3. 웹 앱 개발 - SpringJDBC

JM·2022년 12월 5일
0
post-thumbnail

참고링크

SpringJDBC

  • JDBC 프로그래밍에서 반복적으로 나타나는 부분을 spring이 수행해준다.
  • JDBC의 모든 저수준 세부사항을 스프링 프레임워크가 처리해준다.

Spring JDBC 패키지

  • org.springframework.jdbc.core
    jdbc 템플릿 클래스와 다양한 콜백 인터페이스를 포함하며 관련 클래스를 포함한다.
  • org.springframework.jdbc.datasource
    datasource에 접근을 쉽게하는 유틸리티 클래스와 datasource 구현체 등을 제공한다.
  • org.springframework.jdbc.object
    RDBMS의 조회, 갱신, 저장등을 객체로 제공
  • org.springframework.jdbc.support
    sql exception 변환 기능과 약간의 유틸리티 클래스를 제공하고 있다.

JDBC Template

  • spring jdbc core에서 가장 중요한 클래스
  • 리소스 생성, 소멸을 관리
  • 스테이트먼트의 생성과 실행을 처리
  • sql 조회, 업데이트 저장 프로시저를 호출하고 resultSet 반복호출 등을 실행
  • JDBC 예외 발생 시 org.springframework.dao패키지에 정의되어 있는 일반적인 예외로 변환



SpringJDBC와 raw JDBC 비교

SpringJDBC

  • org.springframework.jdbc.datasource.DriverManagerDataSource 클래스
    • java.sql.DataSource의 구현체
    • 커넥션풀을 사용하지 않음 → 매 요청 시 새로운 Connection 객체 생성 → 실서버에서 사용하기에는 부적절
    • 순수 JDBC에서 DriverManager 클래스를 이용해 Connection 객체를 생성하는 프로세스를 담당
    • 클래스 주석 : Simple implementation of the standard JDBC javax.sql.DataSource interface, configuring the plain old JDBC DriverManager via bean properties, and returning a new Connection from every getConnection call.
  • javax.sql.DataSource 인터페이스
    • 위 클래스가 대표하는(대신하는) 물리적 데이터 소스에 대한 커넥션을 생성하는 factory
    • DriverManager의 대안으로, DB에 대한 커넥션을 가져오는 도구로 추천됨
    • 위 인터페이스는 드라이버 벤더에 의해 구현된다. 아래와 같은 세 가지 종류의 구현 방법이 있다.
      1. 기본 구현 : 표준 Connection 객체를 제공
      2. 커넥션 풀링 구현 : 커넥션 풀에 있는 Connection 객체를 제공. 이 구현법은 중간에 pooling manager를 통해 동작
      3. 분산된 트랜잭션 구현 : 분산된 트랜잭션을 위해 사용되고 커넥션풀에 포함된 Connection 객체를 제공. 이 구현법은 중간에 transaction manager와 pooling manager를 통해 동작
    • DataSource의 property는 수정이 가능하기 때문에, DataSource가 다른 서버로 이동되는 경우, 기존 소스코드를 수정할 필요는 없다.

SpringJdbcConfig.java

@Configuration
@ComponentScan
public class SpringJdbcConfig {

    @Bean
    public DataSource mysqlDataSource(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/spring");
        dataSource.setUsername("root");
        dataSource.setPassword("1111");

        return dataSource;
    }
}

SpringJdbcRepository.java

@Repository
public class SpringJdbcRepository {

    private DataSource dataSource;

    public SpringJdbcRepository(DataSource dataSource){
        this.dataSource = dataSource;
    }

    public int getUserCount(){
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        int result = jdbcTemplate.queryForObject(
                "SELECT COUNT(*) FROM USER", Integer.class
        );
        return result;
    }
}

SpringJdbcTest.java

public class SpringJdbcTest {
    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringJdbcConfig.class);
        SpringJdbcRepository repository = ac.getBean("springJdbcRepository",SpringJdbcRepository.class);
        int queryResult = repository.getUserCount();
        System.out.println(queryResult);
    }
}

raw JDBC

  • 의문점

    • getConnection() 메소드를 통해 DB와 연결된 Connection 객체를 반환받는다. 이때 connection 객체는 새로 생성되는 것일까? 아니 ConnectionPool에 있는 객체의 주소를 받는 것일까?

      새로운 커넥션을 생성한다. 커넥션풀을 사용하려면, 따로 설정해야 한다.

    • 만약 커넥션 객체를 새로 생성한다면, Connection은 내부적으로 소켓으로 통신하는가? 어떤 통신 기법을 사용하는가?

      connection은 서버에서 사용중인 DB에서 정의한 프로토콜을 기반으로 통신한다. 예를 들어, Mysql은 TCP/IP socket을 기반으로 통신하는 프로토콜을 사용한다. 따라서, connection이라 함은 socket을 통해 mysql과 연결되는 객체임을 알 수 있다.

      public class RawJdbcTest {
          public static void main(String[] args) throws SQLException, ClassNotFoundException {
              connectionCreateTest();
          }
      
          public static void connectionCreateTest() throws SQLException, ClassNotFoundException {
              Connection connection1 = RawJdbcConfig.getConnection();
              Connection connection2 = RawJdbcConfig.getConnection();
      
              if(connection1 != connection2){
                  System.out.println("서로 다른 커넥션 객체를 생성합니다.");
              }
          }
      }
      // 출력 : 서로 다른 커넥션 객체를 생성합니다.

RawJdbcConfig.java

public class RawJdbcConfig {
    public static Connection getConnection() throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.cj.jdbc.Driver");

        String dburl = "jdbc:mysql://localhost:3306/spring?useSSL=false";
        String ID = "root";
        String PWD = "1111";

        Connection conn = DriverManager.getConnection(dburl,ID,PWD);
        return conn;
    }
}

RawJdbcTest.java

public class RawJdbcTest {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = RawJdbcConfig.getConnection();
            stmt = conn.createStatement();
            rs = stmt.executeQuery("select id from USER;");
            while(rs.next()) System.out.println(rs.getInt("id"));
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(rs != null) {
                rs.close();
            }
            if(stmt != null) {
                stmt.close();
            }
            if(conn != null) {
                conn.close();
            }
        }
    }
}
profile
나는 사는데로 생각하지 않고, 생각하는데로 살겠다

0개의 댓글