java-mysql数据库连接池

时间:2022-09-12 10:09:10

闲来无事,写了一个MySql数据库连接池

工程结构如图

 

 java-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', 'TEST1@qq.com')");
  dbConn.addBatch("INSERT INTO MEMBER (MID, USERNAME, PASSWORD, EMAIL) VALUES ('1', 'TEST2', 'TEST2', 'TEST1@qq.com')");
  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