SpringBoot中手動實現JDBC連接池

創建一個工具類:JDBCUtils

package com.example.demo.Util;

import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.Properties;
import java.util.Queue;

/**
 * @ClassName: JDBCUtils
 * @Description: 實現連接池效果,初始化10個JDBC連接對象並放入池中,提供方法每次返回一個對象
 * @Author: xuezhouyi
 * @Version: V1.0
 **/
@Slf4j
public class JDBCUtils {

    private static String driver;

    private static String url;

    private static String username;

    private static String password;

    //連接池
    private static Queue<Connection> pool = new LinkedList<>();

    static {
        Properties properties = new Properties();
        InputStream is = null;
        try {
            is = JDBCUtils.class.getClassLoader().getResourceAsStream("mysql.properties");
            properties.load(is);
            driver = properties.getProperty("mysql.driver");
            url = properties.getProperty("mysql.url");
            username = properties.getProperty("mysql.username");
            password = properties.getProperty("mysql.password");
        } catch (Exception e) {
            e.printStackTrace();
        }

        //創建三個連接對象(包裝類對象)放到池子中
        for (int i = 0; i < 10; i++) {
            Connection connection;
            try {
                Class.forName(driver);
                connection = DriverManager.getConnection(url, username, password);
                Connection connectionWrapper = new ConnectionWrapper(connection, pool);
                pool.add(connectionWrapper);
            } catch (Exception e) {
                e.printStackTrace();
            }
            log.info("第" + i + "個連接對象放入池中");
        }
    }

    //返回連接對象
    public static Connection getConnection() {

        Connection connection = null;

        if (pool.size() > 0) {
            connection = pool.poll();
        } else {
            //等待超時,返回一個新創建的對象
            try {
                connection = DriverManager.getConnection(url, username, password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        log.info("取出一個對象後,當前池子中有" + pool.size() + "個對象");
        return connection;
    }

}

實現Connection接口修改close方法

package com.example.demo.Util;

import lombok.extern.slf4j.Slf4j;

import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;
import java.util.Queue;
import java.util.concurrent.Executor;

/**
 * @ClassName: ConnectionWrapper
 * @Description: 實現一個Connection接口重寫close方法將對象歸還池中
 * @Author: xuezhouyi
 * @Version: V1.0
 **/
@Slf4j
public class ConnectionWrapper implements Connection {

    private Connection connection;

    private Queue<Connection> pool;

    public ConnectionWrapper(Connection connection, Queue<Connection> pool) {
        this.connection = connection;
        this.pool = pool;
    }

    @Override
    public Statement createStatement() throws SQLException {
        return null;
    }

    //傳入SQL
    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        PreparedStatement prepareStatement = connection.prepareStatement(sql);
        return prepareStatement;
    }

    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
        return null;
    }

    @Override
    public String nativeSQL(String sql) throws SQLException {
        return null;
    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {

    }

    @Override
    public boolean getAutoCommit() throws SQLException {
        return false;
    }

    @Override
    public void commit() throws SQLException {

    }

    @Override
    public void rollback() throws SQLException {

    }

    //歸還
    @Override
    public void close() throws SQLException {
        pool.offer(this);
        log.info("歸還一個連接對象後,當前池中還剩" + pool.size() + "個對象");
    }

    @Override
    public boolean isClosed() throws SQLException {
        return false;
    }

    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
        return null;
    }

    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {

    }

    @Override
    public boolean isReadOnly() throws SQLException {
        return false;
    }

    @Override
    public void setCatalog(String catalog) throws SQLException {

    }

    @Override
    public String getCatalog() throws SQLException {
        return null;
    }

    @Override
    public void setTransactionIsolation(int level) throws SQLException {

    }

    @Override
    public int getTransactionIsolation() throws SQLException {
        return 0;
    }

    @Override
    public SQLWarning getWarnings() throws SQLException {
        return null;
    }

    @Override
    public void clearWarnings() throws SQLException {

    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        return null;
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        return null;
    }

    @Override
    public Map<String, Class<?>> getTypeMap() throws SQLException {
        return null;
    }

    @Override
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {

    }

    @Override
    public void setHoldability(int holdability) throws SQLException {

    }

    @Override
    public int getHoldability() throws SQLException {
        return 0;
    }

    @Override
    public Savepoint setSavepoint() throws SQLException {
        return null;
    }

    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
        return null;
    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {

    }

    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {

    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return null;
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
        return null;
    }

    @Override
    public Clob createClob() throws SQLException {
        return null;
    }

    @Override
    public Blob createBlob() throws SQLException {
        return null;
    }

    @Override
    public NClob createNClob() throws SQLException {
        return null;
    }

    @Override
    public SQLXML createSQLXML() throws SQLException {
        return null;
    }

    @Override
    public boolean isValid(int timeout) throws SQLException {
        return false;
    }

    @Override
    public void setClientInfo(String name, String value) throws SQLClientInfoException {

    }

    @Override
    public void setClientInfo(Properties properties) throws SQLClientInfoException {

    }

    @Override
    public String getClientInfo(String name) throws SQLException {
        return null;
    }

    @Override
    public Properties getClientInfo() throws SQLException {
        return null;
    }

    @Override
    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
        return null;
    }

    @Override
    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
        return null;
    }

    @Override
    public void setSchema(String schema) throws SQLException {

    }

    @Override
    public String getSchema() throws SQLException {
        return null;
    }

    @Override
    public void abort(Executor executor) throws SQLException {

    }

    @Override
    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {

    }

    @Override
    public int getNetworkTimeout() throws SQLException {
        return 0;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
}

測試類

package com.example.demo;

import com.example.demo.Util.JDBCUtils;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class DemoApplicationTests {

    @Test
    public void contextLoads() throws SQLException {
        final Connection connection = JDBCUtils.getConnection();
        final PreparedStatement pstm = connection.prepareStatement("select * from db");
        final ResultSet resultSet = pstm.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getString("db")+"-"+resultSet.getString("user"));
        }
        final Connection connection1 = JDBCUtils.getConnection();
        final Connection connection2 = JDBCUtils.getConnection();
        connection.close();
        connection1.close();
        connection2.close();
    }

}

測試日誌

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.1.RELEASE)

2019-11-24 20:18:55.617  INFO 4244 --- [           main] com.example.demo.DemoApplicationTests    : Starting DemoApplicationTests on XavierXue with PID 4244 (started by XavierXue in C:\Users\XavierXue\IdeaProjects\apache\demo)
2019-11-24 20:18:55.619  INFO 4244 --- [           main] com.example.demo.DemoApplicationTests    : No active profile set, falling back to default profiles: default
2019-11-24 20:18:56.368  INFO 4244 --- [           main] com.example.demo.DemoApplicationTests    : Started DemoApplicationTests in 1.283 seconds (JVM running for 2.649)
2019-11-24 20:18:56.929  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 第0個連接對象放入池中
2019-11-24 20:18:56.934  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 第1個連接對象放入池中
2019-11-24 20:18:56.938  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 第2個連接對象放入池中
2019-11-24 20:18:56.942  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 第3個連接對象放入池中
2019-11-24 20:18:56.946  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 第4個連接對象放入池中
2019-11-24 20:18:56.951  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 第5個連接對象放入池中
2019-11-24 20:18:56.955  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 第6個連接對象放入池中
2019-11-24 20:18:56.960  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 第7個連接對象放入池中
2019-11-24 20:18:56.963  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 第8個連接對象放入池中
2019-11-24 20:18:56.967  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 第9個連接對象放入池中
2019-11-24 20:18:56.968  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 取出一個對象後,當前池子中有9個對象
sys-mysql.sys
2019-11-24 20:18:56.982  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 取出一個對象後,當前池子中有8個對象
2019-11-24 20:18:56.982  INFO 4244 --- [           main] com.example.demo.Util.JDBCUtils          : 取出一個對象後,當前池子中有7個對象
2019-11-24 20:18:56.982  INFO 4244 --- [           main] com.example.demo.Util.ConnectionWrapper  : 歸還一個連接對象後,當前池中還剩8個對象
2019-11-24 20:18:56.982  INFO 4244 --- [           main] com.example.demo.Util.ConnectionWrapper  : 歸還一個連接對象後,當前池中還剩9個對象
2019-11-24 20:18:56.982  INFO 4244 --- [           main] com.example.demo.Util.ConnectionWrapper  : 歸還一個連接對象後,當前池中還剩10個對象

Process finished with exit code 0

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章