動態加載數據庫連接池

實現背景:對於SQL語句需要在庫中配置的數據源加載問題,無法直接使用外部的數據庫連接池加載動態配置的數據庫

簡單的實現方式是使用JDBC單獨獲取配置信息建立數據庫連接,對於連接頻繁的數據庫連接使用JDBC則不是最好的選擇,所以在此需要了解下動態數據庫連接池的實現

 首先創建初始化動態連接池類

DynamicDataSourcePool.java
package cn.net.topnet.utils;

import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * Created with CosmosRay
 *
 * @author CosmosRay
 * @date 2019/8/15
 * Funciton:初始化連接池
 */
public class DynamicDataSourcePool {
    private static final Log log = LogFactory.getLog(DynamicDataSourcePool.class);
    /**
     *     申明C3p0數據連接池變量
     */
    private ComboPooledDataSource pool = null;

    /**
     * 默認的構造方法
     *
     * @param userName    數據庫用戶名
     * @param pass        數據庫密碼
     * @param url         連接的url
     * @param driverClass 數據驅動
     */
    public DynamicDataSourcePool(String userName, String pass, String url, String driverClass) {
        try {
            //創建對象
            this.pool = new ComboPooledDataSource();
            //設置驅動
            this.pool.setDriverClass(driverClass);
            //設置連接的url
            this.pool.setJdbcUrl(url);
            //設置數據庫用戶名
            this.pool.setUser(userName);
            //設置數據庫密碼
            this.pool.setPassword(pass);
            //當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數
            this.pool.setAcquireIncrement(3);
            //連接關閉時默認將所有未提交的操作回滾
            this.pool.setAutoCommitOnClose(false);
            //獲取連接失敗後該數據源將申明已斷開並永久關閉
            this.pool.setBreakAfterAcquireFailure(false);
            //當連接池用完時客戶端調用getConnection()後等待獲取新連接的時間,超時後將拋出SQLException,如設爲0則無限期等待。單位毫秒。
            this.pool.setCheckoutTimeout(1000);
            //每60秒檢查所有連接池中的空閒連接
            this.pool.setIdleConnectionTestPeriod(60);
            //初始化時獲取10個連接,取值應在minPoolSize與maxPoolSize之間
            this.pool.setInitialPoolSize(10);
            //連接池中保留的最大連接數
            this.pool.setMaxPoolSize(40);
            //連接池最小連接數
            this.pool.setMinPoolSize(5);
            //最大空閒時間,60秒內未使用則連接被丟棄
            this.pool.setMaxIdleTime(60);
            //c3p0是異步操作的,緩慢的JDBC操作通過幫助進程完成。擴展這些操作可以有效的提升性能通過多線程實現多個操作同時被執行
            this.pool.setNumHelperThreads(3);
            log.info("數據庫連接池初始化成功");
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到連接
     *
     * @return
     */
    public Connection getConnection() {
        try {
            return this.pool.getConnection();
        } catch (SQLException e) {
            log.info("獲取連接異常");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 關閉
     */
    public void destroy() {
        if (null != this.pool) {
            this.pool.close();
        }
    }
}

創建連接池的管理類

DynamicDataSourcePoolFactory.java
package cn.net.topnet.utils;

import cn.net.topnet.dao.impl.DataSourceDaoImpl;
import cn.net.topnet.pojo.DataSource;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import org.apache.commons.lang3.StringUtils;

import java.sql.Connection;
import java.util.Hashtable;

/**
 * Created with CosmosRay
 *
 * @author CosmosRay
 * @date 2019/8/15
 * Funciton:該類是連接池的管理類
 */
public class DynamicDataSourcePoolFactory {
    private static final Log log = LogFactory.getLog(DynamicDataSourcePool.class);
    private static Hashtable<String, DynamicDataSourcePool> hashtable = null;
    private static DynamicDataSourcePoolFactory dataSourcePoolFactory;

    public DynamicDataSourcePoolFactory() {

    }

    public static DynamicDataSourcePoolFactory getInstance() {
        if (null == dataSourcePoolFactory) {
            hashtable = new Hashtable<String, DynamicDataSourcePool>();
            dataSourcePoolFactory = new DynamicDataSourcePoolFactory();
        }
        return dataSourcePoolFactory;
    }

    /**
     * 綁定連接池
     *
     * @param key            連接池的名稱必須唯一
     * @param dataSourcePool 對應的連接池
     */
    public void bind(String key, DynamicDataSourcePool dataSourcePool) {
        if (IsBePool(key)) {
            getDynamicDataSourcePool(key).destroy();
        }
        hashtable.put(key, dataSourcePool);
    }

    /**
     * 重新綁定連接池
     *
     * @param key            連接池的名稱必須唯一
     * @param dataSourcePool 對應的連接池
     */
    public void rebind(String key, DynamicDataSourcePool dataSourcePool) {
        if (IsBePool(key)) {
            getDynamicDataSourcePool(key).destroy();
        }
        hashtable.put(key, dataSourcePool);
    }

    /**
     * 刪除動態數據連接池中名稱爲key的連接池
     *
     * @param key
     */
    public void unbind(String key) {
        if (IsBePool(key)) {
            getDynamicDataSourcePool(key).destroy();
        }
        hashtable.remove(key);
    }

    /**
     * 查找動態數據連接池中是否存在名稱爲key的連接池
     *
     * @param key
     * @return
     */
    public boolean IsBePool(String key) {
        return hashtable.containsKey(key);
    }

    /**
     * 根據key返回key對應的連接池
     *
     * @param key
     * @return
     */
    public DynamicDataSourcePool getDynamicDataSourcePool(String key) {
        if (!IsBePool(key)) {
            return null;
        }
        return (DynamicDataSourcePool) hashtable.get(key);

    }

    /**
     * 獲取數據庫連接
     *
     * @param dataSourcePoolName
     * @return
     */
    public Connection getConnection(String dataSourcePoolName) {
        if (StringUtils.isBlank(dataSourcePoolName)) {
            return null;
        }
        Connection conn;
        if (!DynamicDataSourcePoolFactory.getInstance().IsBePool(dataSourcePoolName.trim())) {
            DataSourceDaoImpl dataSourceDao = new DataSourceDaoImpl();
            DataSource dataSource = dataSourceDao.getDataSource(dataSourcePoolName);
            buildDataSourcePool(dataSource);
        }
        conn = DynamicDataSourcePoolFactory.getInstance().getDynamicDataSourcePool(dataSourcePoolName.trim()).getConnection();
        return conn;
    }

    public static String buildDataSourcePool(DataSource dataSource) {
        if (dataSource == null) {
            return "<p style='color:red'>數據源對象爲 null,請檢查數據庫</p>";
        }
        //判斷 數據庫驅動、數據庫連接、數據庫用戶名不爲空  密碼可爲空
        if (StringUtils.isBlank(dataSource.getDriver()) || StringUtils.isBlank(dataSource.getUrl()) || StringUtils.isBlank(dataSource.getUserName())) {
            log.info("================================================================");
            log.info("Error:Database configuration in the support library is incomplete");
            return "<p style='color:red'>Error:Database configuration in the support library is incomplete</p>";
        }
        DynamicDataSourcePoolFactory factory = DynamicDataSourcePoolFactory.getInstance();

        if (factory.IsBePool(dataSource.getName().trim())) {
            return "<p style='color:#F9CC9D'>Info:The data source already exists:" + dataSource.getName().trim()+"</p>";
        }

        DynamicDataSourcePool dataSourcePool = new DynamicDataSourcePool(dataSource.getUserName().trim(), dataSource.getUserPassword().trim(), dataSource.getUrl().trim(), dataSource.getDriver().trim());
        //數據源連接池綁定
        factory.bind(dataSource.getName().trim(), dataSourcePool);
        //判斷數據庫連接池是否註冊成功
        if (factory.IsBePool(dataSource.getName().trim())) {
            log.info("Success:Successfully registered a new database connection pool:" + dataSource.getName().trim());
            return "<p style='color:#7CD03B'>Success:Successfully registered a new database connection pool:" + dataSource.getName().trim()+"</p>";
        } else {
            log.info("Error:Failed to register a new database connection pool:" + dataSource.getName().trim());
            return "<p style='color:red'>Error:Failed to register a new database connection pool:" + dataSource.getName().trim()+"</p>";
        }
    }
}

對於本次實現,我是在外部創建了實例類 DataSource.java

package cn.net.topnet.pojo;

/**
 * Created with CosmosRay
 *
 * @author CosmosRay
 * @date 2019/8/16
 * Funciton: 數據源信息
 */
public class DataSource {
    private String id;
    //數據源別名,連接池綁定名稱
    private String name;
    private String type;
    //數據庫連接驅動
    private String driver;
    //數據庫連接
    private String url;
    //用戶名
    private String userName;
    //用戶密碼
    private String userPassword;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }
}

通過調用管理類DynamicDataSourcePoolFactory.java 中的  buildDataSourcePool(DataSource dataSource) 方法,將數據源動態配置成連接池

獲取數據庫連接  

Connection conn = DynamicDataSourcePoolFactory.getInstance().getConnection(DataSource.getName());

CosmosRay

 

      [email protected]
   CSDN博客
   格言:能力是金錢的另一種保存方式
   版權聲明:本文爲博主原創文章,如需轉載請註明出處

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