閒來無事,寫了一個MySql數據庫連接池
工程結構如圖
源碼如下:
DBConnectioin.java如下
package com.database;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
public class DBConnection {
private Connection conn = null; //數據庫連接句柄
private Statement stm = null;
private boolean used = false; //該鏈接是否正被使用
private boolean inPools = true; //是否在連接池中
private ArrayList<String> batchSql = null; //批量處理sql
public DBConnection(){
}
/**
* Description 構造方法
* @param drivername 數據庫驅動名稱
* @param url 數據庫地址
*/
protected DBConnection(String drivername, String url, String username,
String password){
try{
Class.forName(drivername);
conn = DriverManager.getConnection(url, username, password);
}
catch(Exception e){
e.printStackTrace();
}
}
/**
* Description 構造方法
* @param drivername 數據庫驅動名稱
* @param username 用戶名
* @parma password 密碼
* @param url 數據庫地址
* @param inPools 是否在緩衝池裏
*/
protected DBConnection(String drivername, String url, String username,
String password, boolean inPools){
try{
Class.forName(drivername).newInstance();
conn = DriverManager.getConnection(url, username, password);
this.inPools = inPools;
}
catch(Exception e){
e.printStackTrace();
}
this.inPools = inPools;
}
/**
* 關閉連接
*/
public void closeConn(){
try{
if(conn != null && !conn.isClosed()){
try{
conn.close();
conn = null;
}
catch(SQLException e){
e.printStackTrace();
}
}
}catch(SQLException e){
e.printStackTrace();
}
}
/**
* @return the conn
*/
public Connection getConn() {
return conn;
}
/**
* @param conn the conn to set
*/
private void setConn(Connection conn) {
this.conn = conn;
}
/**
* FunName setAutoCommit
* Description 設置自動提交
* @param bool 是否自動提交
*/
public void setAutoCommit(boolean bool){
try{
if(conn.getAutoCommit() != bool){
conn.setAutoCommit(bool);
closeStm();
createStatement();
}
}
catch(Exception e){
e.printStackTrace();
}
}
/**
* @return the used
*/
protected boolean isUsed() {
return used;
}
/**
* @param used the used to set
*/
protected void setUsed(boolean used) {
this.used = used;
}
/**
* @return the inPools
*/
protected boolean isInPools() {
return inPools;
}
/**
* @param inPools the inPools to set
*/
protected void setInPools(boolean inPools) {
this.inPools = inPools;
}
/**
* FunName execute
* Description 執行sql語句
*/
public boolean execute(String sql){
boolean success = false;
try{
createStatement();
success = stm.execute(sql);
}
catch(Exception e){
e.printStackTrace();
success = false;
}
return success;
}
/**
* FunName addBatch
* Description 添加批量處理sql語句
*/
public void addBatch(String sql){
if(batchSql == null)
batchSql = new ArrayList();
batchSql.add(sql);
}
/**
* FunName batch
* Description 批量執行sql語句
*/
public boolean batch(){
try{
createStatement();
setAutoCommit(false);
stm.execute("START TRANSACTION;");
for(int i = 0; i < batchSql.size(); i++){
stm.addBatch(batchSql.get(i));
}
stm.executeBatch();
conn.commit();
}
catch(Exception e){
try{
conn.rollback();
}
catch(Exception el){
el.printStackTrace();
}
e.printStackTrace();
}
batchSql = null;
setAutoCommit(true);
return true;
}
/**
* FunName query
* Description 執行查詢語句
* @param sql 查詢語句
* @return 查詢結果集ResultSet
*/
public ResultSet query(String sql){
ResultSet rs = null;
try{
createStatement();
rs = stm.executeQuery(sql);
}
catch(Exception e){
e.printStackTrace();
}
return rs;
}
/**
* FunName createStatement
* Description 創建Statement
*/
private void createStatement() throws Exception{
if(stm == null){
stm = conn.createStatement();
}
}
/**
* FunName closeStm
* Description 關閉Statement
*/
protected void closeStm(){
try{
if(stm != null)
stm.close();
}
catch(Exception e){
e.printStackTrace();
}
stm = null;
}
/**
* FunName closeRs
* Description 關閉Result
*/
public void closeRs(ResultSet rs){
try{
if(rs != null)
rs.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
DBConnectionPool.java如下
package com.database;
import java.sql.Connection;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;
/*
*
*/
public class DBConnectionPool {
/**
* 連接地址
*/
private static String url;
/**
* 字符編碼
*/
private static String encoding;
/**
* 驅動程序
*/
private static String drivername;
/**
* 數據庫名
*/
private static String database;
/*
* 用戶名
*/
private static String username;
/*
* 密碼
*/
private static String password;
/**
* 數據庫連接池
*/
private static Vector<DBConnection> pools = new Vector();
/**
* 當前連接池可用連接句柄數據
*/
private static int currConnCount = 0;
/**
* 連接池最高連接數據
*/
private static int maxConnCount = 30;
/**
* 連接池最小連接數據
*/
private static int minConnCount = 10;
/**
* 連接池增長速度
*/
private static int createSpeed = 10;
/**
* 連接池
*/
private static DBConnectionPool dbConnectionPool = null;
/*
* FunName DBConnectionPool
* Description 構造方法
*/
private DBConnectionPool(){
ReadDBProperties readProperties = new ReadDBProperties();
Properties properties = readProperties.getProperties();
drivername = properties.getProperty("drivername"); //從資源文件中讀取數據庫驅動名稱
database = properties.getProperty("database"); //從資源文件中讀取數據庫名稱
username = properties.getProperty("username"); //從資源文件中讀取用戶名
password = properties.getProperty("password"); //從資源文件中讀取密碼
encoding = properties.getProperty("encoding"); //從資源文件中讀取數據庫編碼
url = properties.getProperty("url")+"/"+database
+"?useUnicode=true&characterEncoding="+encoding;//從資源文件中讀取數據庫路徑
int max = 5; //默認連接池中最大連接數
try{
max = Integer.parseInt(properties.getProperty("maxConnCount")); //從資源文件中讀取最大連接數
maxConnCount = max;
}catch(Exception e){
e.printStackTrace();
}
int min = 1; //默認連接池中最小連接數
try{
min = Integer.parseInt(properties.getProperty("minConnCount")); //從資源文件中讀取最小連接數
if(min > max)
min = max;
minConnCount = min;
}catch(Exception e){
e.printStackTrace();
}
int speed = 1; //默認數據庫連接增長速度爲1
try{
speed = Integer.parseInt(properties.getProperty("createSpeed"));//從資源文件中讀取數據庫連接增長速度
if(speed > max)
speed = max;
createSpeed = speed;
}catch(Exception e){
e.printStackTrace();
}
InitConnections();
}
/**
* FunName InitConnections
* Description 初始化連接池pools
*/
private void InitConnections(){
for(int i = 0; i < minConnCount; i++){
DBConnection dbConnection = new DBConnection(drivername, url, username, password);
pools.add(dbConnection);
}
currConnCount = minConnCount;
}
/**
* FunName createConnection
* Description 創建連接句柄
*/
private static void createConnection(){
int leaveCount = maxConnCount - pools.size(); //計算剩下多少個可創建的數據庫連接
int createCount = createSpeed < leaveCount ? createSpeed : leaveCount; //計算此次創建多少個數據庫連接
for(int i = 0; i < createCount; i++){
DBConnection dbConnection = new DBConnection(drivername, url, username, password);
pools.add(dbConnection);
}
currConnCount += createCount; //計算當前可用數據庫連接
}
/**
* 得到一個連接句柄
* @return dbConnection
*/
public static DBConnection getDBConnection(){
//如果未初始化連接池,那麼執行初始化
if(dbConnectionPool == null){
dbConnectionPool = new DBConnectionPool();
}
//連接池連接數量爲0,配置文件出錯
if(pools.size() == 0){
System.out.println("創建連接池失敗,請檢查配置文件!");
return null;
}
//遍歷連接池,尋找一個可用連接
Iterator<DBConnection> it = pools.iterator();
while(it.hasNext()){
//從連接池中得到一個連接
DBConnection dbConnection = it.next();
//判斷是否可用
if(!dbConnection.isUsed()){
//得到連接名柄
Connection connection = dbConnection.getConn();
try{
//如果連接名柄可用,從連接池中返回,否則銷燬
if(connection!=null && !connection.isClosed()){
dbConnection.setUsed(true);
currConnCount--;
return dbConnection;
}
else{
pools.remove(dbConnection);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
//遍歷完連接池也找不到1個可用連接創建新的連接
//判斷是否連接池中的連接數量是否還可增長,可增長則由連接池創建連接,否則返回額外的連接名柄
if(currConnCount <= 0 && pools.size() < maxConnCount){
createConnection();
}
else if(pools.size() >= maxConnCount){
return new DBConnection(drivername, url, username, password, false);
}
return new DBConnection(drivername, url, username, password, false);
}
/**
* FunName close
* Description 連接句柄dbConnection放回連接池
* @param dbConnection
*/
public static void close(DBConnection dbConnection){
//如果是連接池的連接,由連接池回收,否則自動銷燬
if(dbConnection.isInPools()){
//設置連接處於空閒狀態
dbConnection.setUsed(false);
dbConnection.closeStm();
currConnCount++;
}
else
dbConnection.closeConn();
}
/*
* Description 關閉連接池
*/
public static void closePools(){
Iterator<DBConnection> it = pools.iterator();
while(it.hasNext()){
DBConnection dbConnection = it.next();
dbConnection.closeConn();
}
pools.removeAllElements();
if(pools.size() == 0){
System.out.println("連接池關閉成功!");
}
}
/**
* FunName getCurrConnCount
* Description 返回連接池可用連接數
* @return 返回連接池可用連接數
*/
public static int getCurrConnCount() {
return currConnCount;
}
/**
* FunName getConnCount
* Description 返回連接池連接數
* @return 返回連接池連接數
*/
public static int getConnCount(){
return pools.size();
}
}
ReadDBProperties.java如下
package com.database;
import java.io.InputStream;
import java.util.Properties;
public class ReadDBProperties {
private Properties properties;
private String webUrl = "";
public ReadDBProperties(){
properties = new Properties();
InputStream in = null;
try{
Package pack = ReadDBProperties.class.getPackage(); //得到類的包對象
ClassLoader loader = ReadDBProperties.class.getClassLoader(); //得到類的加載路徑對象
webUrl = loader.getResource("").getPath(); //得到類路徑
webUrl = java.net.URLDecoder.decode(webUrl, "UTF-8"); //對路徑進行編碼
webUrl = webUrl.substring(1, webUrl.lastIndexOf("/classes/")); //得到web根路徑
in = loader.getResourceAsStream("db_init.properties"); //得到數據庫配置文件流
properties.load(in); //加載數據庫配置文件
in.close(); //關閉文件流
in = null;
}
catch(Exception e){
e.printStackTrace();
}
}
public Properties getProperties() {
return properties;
}
public String getWebUrl(){
return webUrl;
}
}
DBTest.java如下
package com.database;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.PreparedStatement;
public class DBTest {
public static void main(String args[]){
DBConnection dbConn1 = DBConnectionPool.getDBConnection();
System.out.println("連接池:" + DBConnectionPool.getConnCount());
System.out.println("當前連接池:" + DBConnectionPool.getCurrConnCount());
System.out.println("-----------------");
DBConnection dbConn2 = DBConnectionPool.getDBConnection();
System.out.println("連接池:" + DBConnectionPool.getConnCount());
System.out.println("當前連接池:" + DBConnectionPool.getCurrConnCount());
System.out.println("-----------------");
DBConnection dbConn3 = DBConnectionPool.getDBConnection();
System.out.println("連接池:" + DBConnectionPool.getConnCount());
System.out.println("當前連接池:" + DBConnectionPool.getCurrConnCount());
System.out.println("-----------------");
DBConnectionPool.close(dbConn1);
System.out.println("連接池:" + DBConnectionPool.getConnCount());
System.out.println("當前連接池:" + DBConnectionPool.getCurrConnCount());
System.out.println("-----------------");
DBConnectionPool.close(dbConn2);
DBConnectionPool.close(dbConn3);
System.out.println("連接池:" + DBConnectionPool.getConnCount());
System.out.println("當前連接池:" + DBConnectionPool.getCurrConnCount());
System.out.println("-----------------");
DBConnection dbConn = DBConnectionPool.getDBConnection();
ResultSet rs = dbConn.query("SELECT * FROM MEMBER");
try{
while(rs.next()){
System.out.println("用戶ID:" + rs.getInt("mid"));
System.out.println("用戶名:" + rs.getString("username"));
System.out.println("密碼:" + rs.getString("password"));
}
}
catch(Exception e){
}
System.out.println("連接池:" + DBConnectionPool.getConnCount());
System.out.println("當前連接池:" + DBConnectionPool.getCurrConnCount());
System.out.println("-----------------");
dbConn.addBatch("INSERT INTO MEMBER (USERNAME, PASSWORD, EMAIL) VALUES ('TEST1', 'TEST1', '[email protected]'
)");
dbConn.addBatch("INSERT INTO MEMBER (MID, USERNAME, PASSWORD, EMAIL) VALUES ('1', 'TEST2', 'TEST2', '[email protected]'
)");
dbConn.batch();
DBConnectionPool.close(dbConn);
}
}
資源文件db_init.properties如下
url=jdbc:mysql://localhost:3306
database=mhome
encoding=UTF-8
drivername=com.mysql.jdbc.Driver
username=root
password=root
maxConnCount=2
minConnCount=1
createSpeed=1