2021 Spring Study

Spring 13. DB 연동 (1) - JDBC 프로그래밍부터 알고 가자

Yerim Kim 2021. 1. 20. 20:44

스프링으로 DB 연동 프로그램을 만들기에 앞서, JDBC 프로그래밍을 먼저 공부할 필요가 있다.

 

다음과 같은 방식으로 JDBC 프로그래밍을 해본 적이 있으리라 생각한다. Connection, Statement, DriverManager, ResultSet 등 익숙한 단어들이 보인다.

import java.sql.*;

public class Example {

   static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  
   static final String DB_URL = "jdbc:mysql://localhost/spring5";

   static final String USER = "username";
   static final String PASS = "password";
   
   public static void main(String[] args) {
       Connection conn = null;
       Statement stmt = null;
       
       try {
          Class.forName("com.mysql.jdbc.Driver");

          conn = DriverManager.getConnection(DB_URL,USER,PASS);

          stmt = conn.createStatement();
          String sql = "SELECT id, first, last, age FROM Employees";
          ResultSet rs = stmt.executeQuery(sql);
          ...
          rs.close();
          stmt.close();
          conn.close();
       } catch(SQLException se){
          se.printStackTrace();
       } catch(Exception e){
          e.printStackTrace();
       } finally {
          try {
             if(stmt!=null) { stmt.close(); }
          } catch(SQLException se2){
          }
          try {
             if(conn!=null) { conn.close(); }
          } catch (SQLException se) {
             se.printStackTrace();
          }
       }
    }
}

 

 

위 코드의 18번 line 쯤을 보면, 아래와 같이 DriverManager 로부터 Connection 객체를 얻고있는 것을 확인할 수 있다.

Connection connection = DriverManager.getConnection();

그런데 근래에는 DataSource가 DriverManager의 대체제로서 사용되고 있다.

DataSource 를 사용할 때는 다음과 같이 DataSource 객체로부터 커넥션 객체를 얻는다.

Connection connection = dataSource.getConnection();

 

JDBC 프로그래밍을 할 때 DriverManager 보다는 DataSource를 사용하는 쪽이 선호된다고 한다. 스프링도 DataSource를 사용해서 DB Connection 을 구한다.

 

이제 DriverManager 대신 DataSource를 사용해서 JDBC 프로그래밍을 해보자. 깊게는 안 써볼거고 스프링 사용에 필요한 정도의 지식만 가져갈 것이다.

 

1. DB 테이블 생성

MySQL 에서 spring5practice 라는 데이터베이스를 만들고 member 테이블을 다음과 같이 만들었다.

사용할 DB 테이블

DB 테이블 생성에 사용한 쿼리는 다음과 같다.

create user 'spring5'@'localhost' identified by 'spring5';

create database spring5practice character set=utf8;

grant all privileges on spring5practice.* to 'spring5'@'localhost';

create table spring5practice.MEMBER (
  ID int auto_increment primary key,
  EMAIL varchar(255),
  PASSWORD varchar(100),
  NAME varchar(100),
  REGISTER_DATE datetime,
  unique key (EMAIL)
) engine=InnoDB character set = utf8;

 

2. build.gradle 작성

apply plugin: 'java'

sourceCompatibility = 1.8
targetCompatibility = 1.8
compileJava.options.encoding = "UTF-8"

repositories {
  mavenCentral()
}

dependencies {
  implementation 'org.apache.tomcat:tomcat-jdbc:8.5.27'
  implementation 'mysql:mysql-connector-java:5.1.45'
}

 

3. Member 및 MemberDao, Main 구현

MemberDao 에 selectAll, selectByEmail, create, update, remove 등의 메서드가 들어갈 수 있겠지만 귀찮으므로

Member 수를 알려주는 count() 메서드만 작성할 것이다.

package spring;

import java.time.LocalDateTime;

public class Member {

    private Long id;
    private String email;
    private String password;
    private String name;
    private LocalDateTime registerDateTime;

    public Member(String email, String password, String name, LocalDateTime registerDateTime) {
        this.email = email;
        this.password = password;
        this.name = name;
        this.registerDateTime = registerDateTime;
    }

    public void changePassword(String oldPassword, String newPassword) {
        if (!password.equals(oldPassword)) {
            throw new WrongIdPasswordException();
        }
        this.password = newPassword;
    }

    public Long getId() { return id; }

    public String getEmail() { return email; }

    public String getPassword() { return password; }

    public String getName() { return name; }

    public LocalDateTime getRegisterDateTime() { return registerDateTime; }
}
package spring;

import java.util.List;
import javax.sql.DataSource;

public class MemberDao {

    private DataSource dataSource;

    public MemberDao(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    
    public int count() {
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
            try (
                Statement stmt = connection.createStatement());
                ResultSet resultSet = stmt.executeQuery(
                    "select count(*) from MEMBER")
            ) {
                resultSet.next();
                return resultSet.getInt(1);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            if (connection != null) {
                try { connection.close(); }
                catch (SQLException e) {}
            }
        }
    }
}
import org.apache.tomcat.jdbc.pool.DataSource;
import spring.MemberDao;

public class Main {

    public static void main(String[] args) {
        DataSource dataSource = new DataSource();
        
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost/spring5practice?characterEncoding=utf8");
        dataSource.setUsername("spring5");
        dataSource.setPassword("spring5");
        dataSource.setInitialSize(2);
        dataSource.MaxActive(10);

        MemberDao memberDao = new MemberDao(dataSource);

        System.out.println(memberDao.count());
    }
}

 

Main 클래스를 보면, main 메서드에서 DataSource 객체를 생성해서 MemberDao 객체에게 넘겨주도록 코드를 작성했다.

 

그런데 main 메서드에서 생성한 DataSource 객체는  org.apache.tomcat.jdbc.pool.DataSource 이고,

MemberDao 생성자 매개변수는 javax.sql.DataSource 이다.

 

Java 는 자바 언어를 가지고 데이터베이스에 접근하여 CRUD 할 수 있도록 java.sql 패키지와 javax.sql 패키지를 제공한다. (두 패키지는 논리적으로 하나로 합쳐져도 될 애들인데 어쩌다보니 그냥 그렇게 된 애들이다.)

 

javax.sql.DataSource 는 인터페이스이다. 그리고 org.apache.tomcat.jdbc.pool.DataSource 는 javax.sql.DataSource 인터페이스의 구현체이다.

tomcat jdbc에서 제공하는 DataSource 객체를 사용하면, 커넥션 풀을 사용해서 DB 연결을 관리할 수 있다.

tomcat jdbc가 제공하는 DB 커넥션 풀 기능을 사용하기 위해서 build.gradle에 implementation 'org.apache.tomcat:tomcat-jdbc:8.5.27' 를 추가했던 것이다. (= tomcat jdbc 가 제공하는 DataSource 구현체를 사용하기 위해서 해당 dependency가 필요한 것.)

 

 


출처

스프링 5 프로그래밍 입문 (최범균),

stackoverflow.com/questions/18212727/difference-between-javax-sql-and-java-sql