티스토리 뷰

JDBC란?

https://tose33.tistory.com/743?category=925804 

 

JDBC

Java Database Connectivity JDBC(Java Database Connectivity)는 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API이다. 내가 어떤 프로그램을 만들었고 데이터베이스를 사용하는 상황이다. 데이터베이

tose33.tistory.com

 

JDBC 기본흐름

https://tose33.tistory.com/760?category=925804 

 

JDBC 기본 흐름

https://tose33.tistory.com/743?category=925804 JDBC Java Database Connectivity JDBC(Java Database Connectivity)는 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API이다. 내가 어떤 프로그램을 만..

tose33.tistory.com

 

 

JDBC를 위해 스프링이 제공하는 JdbcTemplate 

JDBC의 기본적인 흐름은 아래와 같다.

JDBC에서 필수적인 드라이버 로드 -> 연결 -> 실행 도구 객체 얻음 ->결과 객체 얻음

이후 얻은 결과 객체에 담긴 정보들로 내가 할 일을 하는 것이다. 

public class Program
{
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        String url = "jdbc:oracle:thin:@localhost:1522/xepdb1"; // 포트번호 1522
        String sql = "SELECT * FROM NOTICE"; // NOTICE 테이블에서 모든 컬럼 얻어옴
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection con = DriverManager.getConnection(url, "LSH", "1234");
        Statement st = con.createStatement();
        ResultSet rs = st.executeQuery(sql);
 
        if(rs.next())
        {
            String title = rs.getString("TITLE");
            System.out.println(title);
        }
 
        rs.close();
        st.close();
        con.close();
    }
}

 

그런데 보면 알겠지만 이 흐름은 항상 동일하게 반복된다. 

 

드라이버 로드 -> 연결 -> 실행 도구 객체 얻음 ->결과 객체 얻음

따라서 이런 구조적인 반복을 줄이기 위해 스프링의 JdbcTemplate 클래스가 여러 기능들을 제공한다.

 

또한 스프링의 JdbcTemplate 클래스의 또 다른 장점은 트랜잭션 관리가 쉽다는 것이다.

 

트랜잭션이란 Git의 merge conflict를 생각하면 쉽다. 

Git 에서 두개의 브랜치가 서로 같은 부분을 다르게 수정해서 병합하려할때 충돌이 일어나는데 이를 merge conflict (병합 충돌) 이라고 한다.

DB에서도 마찬가지로 서로 다른 트랜잭션에서 동시에 같은 부분을 수정하려고 하면 충돌이 일어난다. 

 

기존에는 이런 트랜잭션의 충돌을 방지하기 위해 git과 마찬가지로 한쪽에서 변경 후 커밋해주는 방식을 사용했는데, 스프링에의 JdbcTemplate 클래스는 이런 점들도 쉽게 해결하는듯 하다. 

 

 


 

DataSource

JDBC 에서는 커넥션을 DriverManager로 얻어왔는데 이외에도 JDBC API에는 DataSource를 이용해 DB 연결을 구하는 방법이 담겨있다. 

 

package config;

import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppCtx
{
    @Bean(destroyMethod = "close") // close 메소드는 커넥션 풀에 보관된 Connection을 닫는다
    public DataSource dataSource()
    {
        DataSource ds = new DataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver"); // Driver 클래스 지정
        ds.setUrl("jdbc:mysql://localhost/spring5fs?characterEncoding=utf8");
        ds.setUsername("spring5");
        ds.setPassword("spring5");
        
        return ds;
    }
}

 

DataSource를 스프링 빈으로 등록해서 사용한다. 

 

기본 흐름은: 

DB 연동에 사용할 DataSource를 스프링 빈으로 등록.

DB 연동 기능을 구현한 빈 객체는 DataSource를 주입받아 사용.

 

 

커넥션 풀

Datasource 클래스가 DriverManager 클래스와 다른점은 DataSource 클래스는 커넥션 풀 기능을 제공한다.

커넥션을 얻어오는 것이 많은 시간이 걸리는 일이기 때문에 미리 여러개의 커넥션을 만들어 놓고 사용 여부만 체크하면서 사용중이라면 활성상태로, 반환되면 유휴(idle) 상태로 하는 것.

 

아래와 같이 작동한다. 

public class DbQuery
{
    private DataSource dataSource;

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

    public int count() {
        Connection conn = null;

        try
        {
            conn = dataSource.getConnection(); // 커넥션풀에서 커넥션 갖고오도록 시도
            // try-with-resource 문, try 블록 벗어날시 자동으로 객체 close 실행됨
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("select count(*) from MEMBER"))
            {
                rs.next();
                return rs.getInt(1);
            }
        } catch (SQLException e)
        {
            throw new RuntimeException(e);
        } finally
        {
            if (conn != null) // 최종적으로 커넥션이 있다면 닫는다
                try
                {
                    conn.close(); // 풀에 반환
                } catch (SQLException e) {}
        }
    }

}

 

 

커넥션 풀에 생성된 커넥션은 지속적으로 재사용된다.

그런데 DBMS 설정에 따라 일정 시간 내에 쿼리가 실행되지 않으면 커넥션을 끊기도 한다. 

이때는 커넥션의 연결은 끊겼지만 커넥션은 여전히 풀에 존재하는 상태이기 때문에 해당 커넥션을 갖고온다면 익셉션이 발생한다. 

 

이런 일을 방지하기 위한 속성이 minEvictableIdleTimeMillis, timeBetweenEvictionRunsMillis 이다. 

이 두 속성은 밀리 세컨드 단위 주기로 유휴 커넥션이 유효한지 여부를 검사하고, 최소 유휴시간을 지정한다.

 

@Configuration
public class AppCtx
{
    @Bean(destroyMethod = "close") // close 메소드는 커넥션 풀에 보관된 Connection을 닫는다
    public DataSource dataSource()
    {
        DataSource ds = new DataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver"); // Driver 클래스 지정
        ds.setUrl("jdbc:mysql://localhost/spring5fs?characterEncoding=utf8");
        ds.setUsername("spring5");
        ds.setPassword("spring5");
        ds.setInitialSize(2); // 커넥션풀을 2개 만들어 놓는다
        ds.setMaxActive(10); // 활성 상태 가능한 최대 커넥션 개수 10
        // 10초 주기로 유휴 커넥션이 유효한지 여부 검사, 최소 유휴 시간 3분으로 지정
        ds.setTestWhileIdle(true); // 유휴 커넥션 검사 true
        ds.setMinEvictableIdleTimeMillis(1000 * 60 * 3); // 최소 유휴 시간 3분 설정
        ds.setTimeBetweenEvictionRunsMillis(10 * 1000); // 10초 주기로
        return ds;
    }
}

 

 

 

 

출처 : 스프링5 프로그래밍 입문 (최범균 저) 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함