关于数据库连接池,本文介绍了一种写法。通过继承接口的方式,采用类似builder模式来实现单库连接的连接池。详细写法见以下的四个类。
1.数据库连接信息接口
说明:将驱动、连接、数据库名、数据库密码等数据连接基础信息做成接口。
package com.et.se.db;
public interface IDataBase {
/**
*
* @return 数据库驱动名
* 注意必须加入数据库驱动包
*/
public String getDirver();
/**
*
* @return 数据库连接
*/
public String getConnUrl();
/**
* @return 数据库用户名
*/
public String getUserName();
/**
*
* @return 数据库密码
*/
public String getPassword();
}
2.数据库连接信息接口实现类
说明:该方法是上述接口的一个实现类
package com.et.se.db;
/**
*
* @author wangbao
* 该类的默认驱动为 mysql-connector-java 5.0以上版本
*/
public class Mysql implements IDataBase{
private String connurl;
private String userName;
private String password;
public Mysql(String connurl,String userName,String password){
this.connurl = connurl;
this.userName = userName;
this.password = password;
}
public Mysql(String serverName,String dbName,String userName,String password){
this.connurl = "jdbc:mysql:"+serverName+"/"+dbName;
this.userName = userName;
this.password = password;
}
@Override
public String getConnUrl() {
// TODO Auto-generated method stub
return connurl;
}
@Override
public String getDirver() {
// TODO Auto-generated method stub
return "com.mysql.jdbc.Driver";
}
@Override
public String getPassword() {
// TODO Auto-generated method stub
return password;
}
@Override
public String getUserName() {
// TODO Auto-generated method stub
return userName;
}
}
3.数据库连接类
说明:该方法为单个数据库的连接类,可以脱离连接池来单独使用。
package com.et.se.db;
import java.sql.Connection;
import java.sql.DriverManager;
public class DBConnector {
private IDataBase db;
private Connection conn;
private boolean free = true;
public DBConnector(IDataBase db) {
this.db = db;
}
/**
* 连接数据库
*
* @return 是否连接成功
*/
public Connection connect() {
try {
Class.forName(db.getDirver()).newInstance();
conn = DriverManager.getConnection(db.getConnUrl(), db
.getUserName(), db.getPassword());
System.out.println("数据库连接成功!");
} catch (Exception e) {
System.out.println("数据库连接失败!");
e.printStackTrace();
conn = null;
}
return conn;
}
public Connection getConnection(){
return conn;
}
/**
* 判断连接是否在使用
* 注意:在这个地方使用的是包访问权限,这一项是特地为连接池设置的,对于外面应用的类并不能读到此方法。
* @return
*/
boolean isFree() {
return free;
}
/**
* 设置连接是否空闲
* @param isFree
*/
void setIsFree(boolean isFree) {
this.free = isFree;
}
/**
* 关闭数据库
* @return 数据库是否关闭成功
*/
public boolean close() {
try {
if (conn != null) {
conn.close();
}
System.out.println("关闭数据库成功!");
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 释放连接,为连接池的重写提供接口
* @return
*/
boolean release(){
throw new RuntimeException("do not use the connection pool,can not release.");
}
}
4.连接池
说明:连接池的实现类
package com.et.se.db;
import java.util.ArrayList;
import java.util.List;
public class DBConnectPool {
private int iniSize = 2; //连接池的初始大小
private int addSize = 2; //每次增加的大小
private int maxSize = 4; //最大的大小
private IDataBase db;
private List<DBConnector> connections = null; //连接池,初始为空
public DBConnectPool(IDataBase db){
this.db = db;
iniPool();
}
/**
* 初始化连接池
*/
public void iniPool(){
connections = new ArrayList<DBConnector>();
connections.addAll(addPool(iniSize));
}
/**
* 增加连接数
* @param size 要增加的数目
* @return
*/
public List<DBConnector> addPool(int size){
List<DBConnector> subList = new ArrayList<DBConnector>();
for(int i=0;i<size;i++){
DBConnector conn = new DBPoolConnector(db);
conn.connect();
subList.add(conn);
}
return subList;
}
/**
* 判断连接数是否超过连接池的最大连接数
* @return 是 否
*/
public boolean isOverRange(){
return connections.size()>=maxSize;
}
/**
* 获得空闲连接
* @return 连接
*/
public DBConnector getConnection(){
for(DBConnector conn:connections){
if(conn.isFree()){
conn.setIsFree(false);
return conn;
}
}
if(isOverRange()) {
throw new RuntimeException("The connection number is over range.");
}
else{
int size = addSize;
if((connections.size()+size)>maxSize) size = maxSize - connections.size();
List<DBConnector> subPool= addPool(size);
connections.addAll(subPool);
return subPool.get(0);
}
}
/**
* 设置连接为空闲状态
* @param conn
*/
public void freeConnection(DBConnector conn){
conn.setIsFree(true);
}
/**
* 释放所有的空闲连接
*/
public void releaseAllFree(){
List<DBConnector> subPool = new ArrayList<DBConnector>();
for(DBConnector conn:connections)
if(conn.isFree()){
subPool.add(conn);
conn.close();
}
connections.removeAll(subPool);
}
/**
* 释放连接
* @param conn 要释放的连接
*/
public void release(DBConnector conn){
conn.release();
connections.remove(conn);
}
/**
* 释放所有连接
*/
public void release(){
for(DBConnector conn:connections)
{
conn.release();
}
connections.removeAll(connections);
}
/**
* 设置初始化最大连接数
* @param iniSize
*/
public void setIniSize(int iniSize) {
this.iniSize = iniSize;
}
/**
* 设置每次递增的最大数目
* @param addSize
*/
public void setAddSize(int addSize) {
this.addSize = addSize;
}
/**
* 设置连接池的最大数目
* @param maxSize
*/
public void setMaxSize(int maxSize) {
this.maxSize = maxSize;
}
/**
* 连接池内部类,用于管理DBConnector安全性,屏蔽close功能
* @author wangbao
*
*/
class DBPoolConnector extends DBConnector{
public DBPoolConnector(IDataBase db) {
super(db);
// TODO Auto-generated constructor stub
}
@Override
boolean release(){
return super.close();
}
@Override
public boolean close(){
throw new RuntimeException("Can not close,please use the Connection Pool close this connection.");
}
}
//测试编码
public static void main(String[] args){
IDataBase db = new Mysql("//localhost", "etocr-jy", "root","soft123456");
DBConnectPool pool = new DBConnectPool(db);
DBConnector conn1 = pool.getConnection();
DBConnector conn2 = pool.getConnection();
DBConnector conn3 = pool.getConnection();
DBConnector conn4= pool.getConnection();
//conn.close();
pool.release();
}
}
5.测试源码
//测试编码
public static void main(String[] args){
IDataBase db = new Mysql("//localhost", "etocr-jy", "root","soft123456");
DBConnectPool pool = new DBConnectPool(db);
DBConnector conn1 = pool.getConnection();
DBConnector conn2 = pool.getConnection();
DBConnector conn3 = pool.getConnection();
DBConnector conn4= pool.getConnection();
//conn.close();
pool.release();
}
}