Java Servlet[6]

BaeSeBinยท2025๋…„ 1์›” 3์ผ

Java Servlet

๋ชฉ๋ก ๋ณด๊ธฐ
6/7

๐ŸงConnection Pool ์ด์šฉํ•˜๊ธฐ

Connection Pooling ์ค‘์—์„œ HikariCP ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Connection Pool ์ด์šฉํ•จ
1. HikariConfig ๊ฐ์ฒด ์ƒ์„ฑ์„ ํ†ตํ•ด ์„ค์ •์„ ์ •์˜ํ•จ.
๋‚ด ์ƒ๊ฐ : HikariConfig ๊ฐ์ฒด๋Š” Connection Pool ์„ค์ • ํ•„์š” ์ •๋ณด ๊ฐ์ฒด์ž„
    @Test
    public void testHikariCP() throws Exception {

        HikariConfig config = new HikariConfig();
        config.setDriverClassName("org.mariadb.jdbc.Driver");
        config.setJdbcUrl("jdbc:mariadb://localhost:3306/webdb");
        config.setUsername("webuser");
        config.setPassword("webuser");
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");

        HikariDataSource ds = new HikariDataSource(config);
        Connection connection = ds.getConnection();

        System.out.println(connection);

        connection.close();

    }
2. HikariConfig๋ฅผ ํ†ตํ•ด HikariDataSource๋ฅผ ์ƒ์„ฑํ•จ.
DataSource๋Š” Connection Pool์˜ ๊ตฌํ˜„ ๊ฐ์ฒด์ž„
HikariDataSource๋Š” getConnection()์„ ์ œ๊ณตํ•จ์œผ๋กœ ์ด๋ฅผ ์ด์šฉํ•ด์„œ Connection ๊ฐ์ฒด๋ฅผ ์–ป์–ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.
remind : Connection ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด db์™€ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ์—ญํ• 
    @Test
    public void testHikariCP() throws Exception {

        HikariConfig config = new HikariConfig();
        config.setDriverClassName("org.mariadb.jdbc.Driver");
        config.setJdbcUrl("jdbc:mariadb://localhost:3306/webdb");
        config.setUsername("webuser");
        config.setPassword("webuser");
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");

        HikariDataSource ds = new HikariDataSource(config);
        Connection connection = ds.getConnection();

        System.out.println(connection);

        connection.close();

    }

๐ŸงDAO์™€ @Cleanup

์ฑ…์ž„๊ณผ ์—ญํ•  ๋ถ„๋ฆฌ ์›์น™์— ๋”ฐ๋ผ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ์„œ๋น„์Šค๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋จ
TodoService <-> TodoDAO <-> DB

๐Ÿง์‹ฑ๊ธ€ํ†ค ๋ฐฉ์‹(ENUM)์„ ์‚ฌ์šฉํ•˜์—ฌ ConnectionUtil ํด๋ž˜์Šค ๊ตฌํ˜„

package org.zerock.jdbcex.dao;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.sql.Connection;

public enum ConnectionUtil {

    INSTANCE;

    private HikariDataSource ds;

    ConnectionUtil()  {
        HikariConfig config = new HikariConfig();
        config.setDriverClassName("org.mariadb.jdbc.Driver");
        config.setJdbcUrl("jdbc:mariadb://localhost:3306/webdb");
        config.setUsername("webuser");
        config.setPassword("webuser");
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");

        ds = new HikariDataSource(config);
    }

    public Connection getConnection()throws Exception {
        return ds.getConnection();
    }

}
์ด๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€์—์„œ๋Š” ConnectionUtil.INSTANCE.getConnection()์„ ํ†ตํ•ด Connection์„ ์–ป์„ ์ˆ˜ ์žˆ์Œ.

๐ŸงTodoDAO ํด๋ž˜์Šค ๊ตฌํ˜„(ํ˜„์žฌ ์‹œ๊ฐ„ ๊ฐ€์ ธ์˜ค๋Š” ์ฟผ๋ฆฌ ์‚ฝ์ž… ๋˜์–ด ์žˆ์Œ)

package org.zerock.jdbcex.dao;

import lombok.Cleanup;
import org.zerock.jdbcex.domain.TodoVO;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class TodoDAO {


    public String getTime(){

        String now = null;

        try(Connection connection = ConnectionUtil.INSTANCE.getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement("select now()");
            ResultSet resultSet = preparedStatement.executeQuery();
        ) {

            resultSet.next();

            now = resultSet.getString(1);
        }catch(Exception e){
            e.printStackTrace();
        }
        return now;
    }

๐ŸงLombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์† @Cleanup ์‚ฌ์šฉํ•˜์—ฌ TodoDAO ํด๋ž˜์Šค ๊ตฌํ˜„(์œ„์™€ ๋™์ผํ•œ ์ฝ”๋“œ์ž„)

package org.zerock.jdbcex.dao;

import lombok.Cleanup;
import org.zerock.jdbcex.domain.TodoVO;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class TodoDAO {
 public String getTime2() throws Exception {

        @Cleanup Connection connection = ConnectionUtil.INSTANCE.getConnection();
        @Cleanup PreparedStatement preparedStatement = connection.prepareStatement("select now()");
        @Cleanup ResultSet resultSet = preparedStatement.executeQuery();

        resultSet.next();

        String now = resultSet.getString(1);

        return now;
    }
}

๐ŸงTodoVO๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ DB์— ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ธฐ๋Šฅ(insert ์ฟผ๋ฆฌ ์‹คํ–‰ ์ฝ”๋“œ)์„ TodoDAO์— ๊ตฌํ˜„ํ•˜๊ธฐ

DAO๋Š” ์ฑ…์ž„๊ณผ ์—ญํ•  ๋ถ„๋ฆฌ ์›์น™์— ์˜ํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ๊ธฐ๋Šฅ(insert)์„ ํ•˜๋Š” ๊ฒƒ์ด์ง€ ์‹ค์ œ ๊ฐ’๊นŒ์ง€ ์ž…๋ ฅ ๋ฐ›๊ณ  ๊ฐ’์„ DB์— ์‚ฝ์ž… ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹˜ / ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š” ๊ฒƒ์€ ์„œ๋น„์Šค ๊ณ„์ธต์—์„œ DAO์—๊ฒŒ ๊ฐ’์„ ์ „๋‹ฌํ•˜๊ณ  ํ›„์— ์ž…๋ ฅ๋ฐ›์€ ๋ฐ์ดํ„ฐ ๊ฐ’์„ ํ†ตํ•ด DAO๋Š” DB์— ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ์—ญํ• ์„ ํ•˜๊ฒŒ ๋จ.
package org.zerock.jdbcex.dao;

import lombok.Cleanup;
import org.zerock.jdbcex.domain.TodoVO;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class TodoDAO {

    public void insert(TodoVO vo) throws Exception {
        String sql = "insert into tbl_todo (title, dueDate, finished) values (?, ?, ?)";

        @Cleanup Connection connection = ConnectionUtil.INSTANCE.getConnection();
        @Cleanup PreparedStatement preparedStatement = connection.prepareStatement(sql);

        preparedStatement.setString(1, vo.getTitle());
        preparedStatement.setDate(2, Date.valueOf(vo.getDueDate()));
        preparedStatement.setBoolean(3, vo.isFinished());

        preparedStatement.executeUpdate();

    }
๐ŸงString sql ์•ˆ์—์„œ values ์•ˆ์— '?'๊ฐ’์€ ๋‚˜์ค‘์— ์ „๋‹ฌํ•  ๋ฐ์ดํ„ฐ๋“ค์„ ์ง€์ •ํ•˜๋Š”๋ฐ PreparedStatement.setXXX()๋ฅผ ์ด์šฉํ•ด์„œ ์‹ค์ œ ๊ฐ’๋“ค์„ ์ง€์ •ํ•จ.
setXXX() ๋ฉ”์„œ๋“œ: ์ฟผ๋ฆฌ ๋‚ด์—์„œ ?(ํ”Œ๋ ˆ์ด์Šคํ™€๋”)๋กœ ํ‘œ์‹œ๋œ ์œ„์น˜์— ๊ฐ’์„ ๋ฐ”์ธ๋”ฉ.
import java.sql.*;

public class PreparedStatementExample {
    public static void main(String[] args) {
        String query = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)";
        
        try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbname", "username", "password");
             PreparedStatement preparedStatement = connection.prepareStatement(query)) {

            // ๋ฐ”์ธ๋”ฉํ•  ๊ฐ’ ์„ค์ •
            preparedStatement.setInt(1, 101); // ์ฒซ ๋ฒˆ์งธ ?์— ์ •์ˆ˜ ๊ฐ’ 101 ์„ค์ •
            preparedStatement.setString(2, "Alice"); // ๋‘ ๋ฒˆ์งธ ?์— ๋ฌธ์ž์—ด "Alice" ์„ค์ •
            preparedStatement.setInt(3, 30); // ์„ธ

๐ŸงTodoDAO์˜ ๋ชฉ๋ก ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ

package org.zerock.jdbcex.dao;

import lombok.Cleanup;
import org.zerock.jdbcex.domain.TodoVO;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class TodoDAO {
 public List<TodoVO> selectAll()throws Exception  {

        String sql = "select * from tbl_todo";

        @Cleanup Connection connection = ConnectionUtil.INSTANCE.getConnection();
        @Cleanup PreparedStatement preparedStatement = connection.prepareStatement(sql);
        @Cleanup ResultSet resultSet = preparedStatement.executeQuery();


        List<TodoVO> list = new ArrayList<>();

        while(resultSet.next()) {
            TodoVO vo = TodoVO.builder()
                    .tno(resultSet.getLong("tno"))
                    .title(resultSet.getString("title"))
                    .dueDate( resultSet.getDate("dueDate").toLocalDate())
                    .finished(resultSet.getBoolean("finished"))
                    .build();

            list.add(vo);
        }

        return list;
    }
}

๐ŸงTodoDAO์˜ ์กฐํšŒ ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ

package org.zerock.jdbcex.dao;

import lombok.Cleanup;
import org.zerock.jdbcex.domain.TodoVO;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class TodoDAO {
public TodoVO selectOne(Long tno)throws Exception {

        String sql = "select * from tbl_todo where tno = ?";

        @Cleanup Connection connection = ConnectionUtil.INSTANCE.getConnection();
        @Cleanup PreparedStatement preparedStatement = connection.prepareStatement(sql);

        preparedStatement.setLong(1, tno);

        @Cleanup ResultSet resultSet = preparedStatement.executeQuery();

        resultSet.next();
        TodoVO vo = TodoVO.builder()
                .tno(resultSet.getLong("tno"))
                .title(resultSet.getString("title"))
                .dueDate( resultSet.getDate("dueDate").toLocalDate())
                .finished(resultSet.getBoolean("finished"))
                .build();

        return vo;
    }
}

๐ŸงTodoDAO์˜ ์‚ญ์ œ/์ˆ˜์ • ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ

// delete ์ฟผ๋ฆฌ ์‚ฌ์šฉ
package org.zerock.jdbcex.dao;

import lombok.Cleanup;
import org.zerock.jdbcex.domain.TodoVO;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class TodoDAO {
  public void deleteOne(Long tno) throws Exception {

        String sql = "delete from tbl_todo where tno = ?";

        @Cleanup Connection    connection = ConnectionUtil.INSTANCE.getConnection();
        @Cleanup PreparedStatement preparedStatement = connection.prepareStatement(sql);

        preparedStatement.setLong(1, tno);

        preparedStatement.executeUpdate();
    }
 }
// ์ˆ˜์ • ๊ธฐ๋Šฅ ์‚ฌ์šฉํ•˜๊ธฐ
package org.zerock.jdbcex.dao;

import lombok.Cleanup;
import org.zerock.jdbcex.domain.TodoVO;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class TodoDAO {
   public void updateOne(TodoVO todoVO)throws Exception{

        String sql = "update tbl_todo set title =?, dueDate = ?, finished = ? where tno =?";

        @Cleanup Connection connection = ConnectionUtil.INSTANCE.getConnection();
        @Cleanup PreparedStatement preparedStatement = connection.prepareStatement(sql);

        preparedStatement.setString(1, todoVO.getTitle());
        preparedStatement.setDate(2, Date.valueOf(todoVO.getDueDate()));
        preparedStatement.setBoolean(3, todoVO.isFinished());
        preparedStatement.setLong(4, todoVO.getTno());

        preparedStatement.executeUpdate();
    }
}

0๊ฐœ์˜ ๋Œ“๊ธ€