JDBC數據庫鏈接池 - (Driver:Mysql, 可替換爲其餘Driver)

不經過鏈接池鏈接數據庫時,主要有兩大劣勢:java

1.每次操做數據庫均需鏈接數據庫,耗時;mysql

2.每次鏈接數據庫均須要單獨的線程,消耗內存嚴重,容易致使服務器宕機。sql

直接上代碼:數據庫

鏈接池接口,提供鏈接和建立鏈接:服務器

 

/** 
 * @projectName:JavaProxy 
 * @fileName:IPool.java 
 * @packageName:club.younge.jdbc 
 * @date:2016年10月5日下午1:21:38 
 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. 
 * 
 */  
  
package club.younge.jdbc;

/** 
 * @className:IPool 
 * @function: TODO ADD FUNCTION.  
 * @reason:   TODO ADD REASON. 
 * @date:     2016年10月5日 下午1:21:38
 * @author   Younge 
 * @version   
 * @since    JDK 1.8 
 * @see       
 */
public interface IPool {
	public PooledConnection getConnection();
	public void createConnections(int count);
}

 

鏈接池實現類。ide

 

/** 
 * @projectName:JavaProxy 
 * @fileName:JdbcPool.java 
 * @packageName:club.younge.jdbc 
 * @date:2016年10月5日下午1:23:58 
 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. 
 * 
 */  
  
package club.younge.jdbc;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Vector;

import com.mysql.jdbc.Driver;

/** 
 * @className:JdbcPool 
 * @function: TODO ADD FUNCTION.  
 * @reason:   TODO ADD REASON. 
 * @date:     2016年10月5日 下午1:23:58
 * @author   Younge 
 * @version   
 * @since    JDK 1.8 
 * @see       
 */
public class JdbcPool implements IPool {
	
	private String jdbcDriver;
	private String jdbcUser;
	private String jdbcPass;
	private String jdbcUrl;
	private int initConnCount;
	private int maxConnCount;
	private int incrementCount;
	
	private Vector<PooledConnection> vector = new Vector<>();
	
	public void init(){
		InputStream in = JdbcPool.class.getClassLoader().getResourceAsStream("club/younge/jdbc/jdbc.properties");
		Properties properties = new Properties();
		try {
			properties.load(in);
			this.jdbcDriver = properties.getProperty("jdbcDriver");
			this.jdbcUrl = properties.getProperty("jdbcUrl");
			this.jdbcPass = properties.getProperty("jdbcPass");
			this.jdbcUser = properties.getProperty("jdbcUser");
			this.initConnCount = Integer.parseInt(properties.getProperty("initalConnCount"));
			this.maxConnCount = Integer.parseInt(properties.getProperty("maxConnCount"));
			this.incrementCount = Integer.parseInt(properties.getProperty("incrementCount"));
			Driver driver = (Driver) Class.forName(jdbcDriver).newInstance();
			DriverManager.registerDriver(driver);  //註冊以後,每次建立鏈接時不用再加載驅動
			createConnections(initConnCount); //建立初始鏈接
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}
	@Override
	public  synchronized PooledConnection getConnection() {
		if (vector.size() <= 0) {
			System.out.println("The pool has no connection to provided!");
			throw new RuntimeException("The pool has no connection to provided!");
		}
		PooledConnection conn = getActiveConnection();
		if (conn == null) {
			createConnections(incrementCount);
			conn = getActiveConnection();
			while(conn == null){
				try {
					Thread.sleep(300);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				conn = getActiveConnection();
			}
		}
		
		return conn;
	}
	
	private  PooledConnection getActiveConnection(){
		for (PooledConnection connection : vector) {
			if (!connection.isBusy()) {
				Connection conn = connection.getConn();
				try {
					if (!conn.isValid(0)) {
						conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPass);
						connection.setConn(conn);
					}
				} catch (SQLException e) {
					e.printStackTrace();
				}
				connection.setBusy(true);
				return connection;
			}
		}
		return null;
	}

	@Override
	public void createConnections(int count) {
		for (int i = 0; i < count; i++) {
			if (maxConnCount > 0 && vector.size() >= maxConnCount) {
				System.out.println("The pool connection number has reached max count!");
				throw new RuntimeException("The pool connection number has reached max count!");
			}
			try {
				Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPass);
				vector.add(new PooledConnection(false, conn));
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

	}

}

自定義鏈接類,封裝數據庫的鏈接類。測試

 

 

/** 
 * @projectName:JavaProxy 
 * @fileName:PooledConnection.java 
 * @packageName:club.younge.jdbc 
 * @date:2016年10月5日下午1:24:23 
 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. 
 * 
 */  
  
package club.younge.jdbc;

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

import com.mysql.jdbc.Statement;

/** 
 * @className:PooledConnection 
 * @function: TODO ADD FUNCTION.  
 * @reason:   TODO ADD REASON. 
 * @date:     2016年10月5日 下午1:24:23
 * @author   Younge 
 * @version   
 * @since    JDK 1.8 
 * @see       
 */
public class PooledConnection {
	private boolean isBusy;
	private Connection conn;
	
	public PooledConnection() {
	}
	
	public PooledConnection(boolean isBusy, Connection conn){
		this.isBusy = isBusy;
		this.conn = conn;
	}
	
	public ResultSet querySql(String sql){
		ResultSet rs = null;
		try {
			Statement statement = (Statement) this.conn.createStatement();
			rs = statement.executeQuery(sql);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return rs;
	}
	
	public boolean isBusy() {
		return isBusy;
	}

	public void setBusy(boolean isBusy) {
		this.isBusy = isBusy;
	}

	public Connection getConn() {
		return conn;
	}

	public void setConn(Connection conn) {
		this.conn = conn;
	}
	public void close(){
		this.isBusy = false;
	}
	
}

鏈接池單例模式實現,採用內部類懶加載方式,類加載時線程互斥。this

 

 

/** 
 * @projectName:JavaProxy 
 * @fileName:DBManager.java 
 * @packageName:club.younge.jdbc 
 * @date:2016年10月5日下午2:27:10 
 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. 
 * 
 */  
  
package club.younge.jdbc;  
/** 
 * @className:DBManager 
 * @function: TODO ADD FUNCTION.  
 * @reason:   TODO ADD REASON. 
 * @date:     2016年10月5日 下午2:27:10
 * @author   Younge 
 * @version   
 * @since    JDK 1.8 
 * @see       
 */
public class DBManager {
	private static final class CreatePool{//類的加載過程是線程互斥的,同時實現懶加載,雙檢查鎖存在問題(建立對象與賦值分開進行)
		//具體參看博客http://blog.csdn.net/yongaini10/article/details/52738866
		public static JdbcPool pool = new JdbcPool();
	}
	
	public static JdbcPool getJdbcPool(){
		return CreatePool.pool;
	}
}

測試類:.net

 

 

/** 
 * @projectName:JavaProxy 
 * @fileName:PoolTest.java 
 * @packageName:club.younge.test 
 * @date:2016年10月5日下午3:22:41 
 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. 
 * 
 */  
  
package club.younge.test;

import java.sql.ResultSet;
import java.sql.SQLException;

import club.younge.jdbc.DBManager;
import club.younge.jdbc.JdbcPool;
import club.younge.jdbc.PooledConnection;

/** 
 * @className:PoolTest 
 * @function: TODO ADD FUNCTION.  
 * @reason:   TODO ADD REASON. 
 * @date:     2016年10月5日 下午3:22:41
 * @author   Younge 
 * @version   
 * @since    JDK 1.8 
 * @see       
 */
public class PoolTest {
	private static JdbcPool pool;
	
	public static void main(String[] args) throws SQLException {
		pool = DBManager.getJdbcPool();
		pool.init();
		for (int i = 0; i < 100; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					query();
				}
			}).start();
		}
		
		
		
	}
	
	public synchronized static void query(){
		System.err.println("\nCurrent thread is " + Thread.currentThread().getName());
		String sql = "select * from student;";
		PooledConnection connection = pool.getConnection();
		ResultSet rs = connection.querySql(sql);
		try {
			while(rs.next()){
				System.out.print(rs.getString("SID") + " ");
				System.out.print(rs.getString("SNAME") + " ");
				System.out.print(rs.getString("SAGE") + " ");
				System.out.print(rs.getString("SSEX") + " \n");
			}
			rs.close();
			connection.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}
}

屬性文件,jdbc.properties:線程

 

 

jdbcDriver=com.mysql.jdbc.Driver
#請自行更改數據庫鏈接信息
jdbcUrl=jdbc:mysql://127.0.0.1/test
jdbcUser=root
jdbcPass=xxxxx 

#initial connection count of jdbc pool
initalConnCount=10

#maximum connection count of jdbc pool
maxConnCount=100

#increment count of jdbc pool
incrementCount=2