自己实现的一个简单的数据库连接池

Posted 小琪子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自己实现的一个简单的数据库连接池相关的知识,希望对你有一定的参考价值。

      自己突然就找到了以前学习的感觉,要不是完了这几个月英爱能找一份比现在好点的工作,说实话还是有点后悔,但是没关系,从现在开始加油还来得及。

今天首先学的是数据库连接,就想到了实现一个数据库连接池,虽然很Lower 但是还是记录下来,一步一个脚印.

首先实现方法是创建一个连接池对象,里面放一个List对象用来保存数据库连接,自己写一个类,实现Connection对象,在里面的close方法里面将连接还给连接池。

然后在从数据库连接池中获取数据的时候用removeFirst方法,移除并返回第一个对象,好的废话不多说上代码

package com.mysql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class JDBC_POOL {
	private static final String URL = "jdbc:mysql://localhost:3306/JDBC_TEST?useUnicode=true&characterEncoding=UTF-8";
	private static final String DRIVER = "com.mysql.jdbc.Driver";
	private static final String USER_NAME = "root";
	private static final String PASSWORD = "dbq228367/";
	/**
	 * 用来装连接池的容器
	 */
	public static LinkedList<myConnection> list = new LinkedList<myConnection>();
	
	/**
	 * 设置容器的大小
	 */
	public static int size = 100;
	
	static{
		 try{
			 for(int i=0;i<3;i++){
				 Connection conn = DriverManager.getConnection(URL, USER_NAME, PASSWORD);
				 System.out.println("创建了数据库连接 : " + conn + " : " + conn.hashCode());
				 myConnection mc = new myConnection(conn);
				 list.add(mc);
			 }	 
		 }catch(Exception e){
			 System.out.println(e.getMessage());
			 e.printStackTrace();
		 }
	}
	
	public myConnection getConnection()throws Exception{
		if(list.size()==0 || list.size()<0){
			//连接池已经满了
			throw new Exception("连接池已经没有连接对象");
		}else{
			System.out.println("程序获取连接对象 : " + list.get(0).getConnection());
			return list.removeFirst();
		}
	}
}

  然后是实现Connection接口的自定义类

package com.mysql;

import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;

public class myConnection implements Connection{

	private Connection conn;
	
	public myConnection(Connection conn){
		this.conn = conn;
	}

	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		// TODO Auto-generated method stub
		return conn.unwrap(iface);
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		// TODO Auto-generated method stub
		return conn.isWrapperFor(iface);
	}

	@Override
	public Statement createStatement() throws SQLException {
		// TODO Auto-generated method stub
		return conn.createStatement();
	}

	@Override
	public PreparedStatement prepareStatement(String sql) throws SQLException {
		// TODO Auto-generated method stub
		return conn.prepareStatement(sql);
	}

	@Override
	public CallableStatement prepareCall(String sql) throws SQLException {
		// TODO Auto-generated method stub
		return conn.prepareCall(sql);
	}

	@Override
	public String nativeSQL(String sql) throws SQLException {
		// TODO Auto-generated method stub
		return conn.nativeSQL(sql);
	}

	@Override
	public void setAutoCommit(boolean autoCommit) throws SQLException {
		// TODO Auto-generated method stub
		conn.setAutoCommit(autoCommit);
	}

	@Override
	public boolean getAutoCommit() throws SQLException {
		// TODO Auto-generated method stub
		return conn.getAutoCommit();
	}

	@Override
	public void commit() throws SQLException {
		// TODO Auto-generated method stub
		conn.commit();
	}

	@Override
	public void rollback() throws SQLException {
		// TODO Auto-generated method stub
		conn.rollback();
	}

	@Override
	public void close() throws SQLException {
		// TODO Auto-generated method stub
		//在这里将连接对象还给连接池
		System.out.println("将连接对象还给连接池  : " + conn);
		JDBC_POOL.list.add(new myConnection(conn));
	}

	@Override
	public boolean isClosed() throws SQLException {
		// TODO Auto-generated method stub
		return conn.isClosed();
	}

	@Override
	public DatabaseMetaData getMetaData() throws SQLException {
		// TODO Auto-generated method stub
		return conn.getMetaData();
	}

	@Override
	public void setReadOnly(boolean readOnly) throws SQLException {
		// TODO Auto-generated method stub
		conn.setReadOnly(readOnly);
	}

	@Override
	public boolean isReadOnly() throws SQLException {
		// TODO Auto-generated method stub
		return conn.isReadOnly();
	}

	@Override
	public void setCatalog(String catalog) throws SQLException {
		// TODO Auto-generated method stub
		conn.setCatalog(catalog);
	}

	@Override
	public String getCatalog() throws SQLException {
		// TODO Auto-generated method stub
		return conn.getCatalog();
	}

	@Override
	public void setTransactionIsolation(int level) throws SQLException {
		// TODO Auto-generated method stub
		conn.setTransactionIsolation(level);
	}

	@Override
	public int getTransactionIsolation() throws SQLException {
		// TODO Auto-generated method stub
		return conn.getTransactionIsolation();
	}

	@Override
	public SQLWarning getWarnings() throws SQLException {
		// TODO Auto-generated method stub
		return conn.getWarnings();
	}

	@Override
	public void clearWarnings() throws SQLException {
		// TODO Auto-generated method stub
		conn.clearWarnings();
	}

	@Override
	public Statement createStatement(int resultSetType, int resultSetConcurrency)
			throws SQLException {
		// TODO Auto-generated method stub
		return conn.createStatement(resultSetType, resultSetConcurrency);
	}

	@Override
	public PreparedStatement prepareStatement(String sql, int resultSetType,
			int resultSetConcurrency) throws SQLException {
		// TODO Auto-generated method stub
		return conn.prepareStatement(sql, resultSetType,resultSetConcurrency);
	}

	@Override
	public CallableStatement prepareCall(String sql, int resultSetType,
			int resultSetConcurrency) throws SQLException {
		// TODO Auto-generated method stub
		return conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetConcurrency);
	}

	@Override
	public Map<String, Class<?>> getTypeMap() throws SQLException {
		// TODO Auto-generated method stub
		return conn.getTypeMap();
	}

	@Override
	public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
		// TODO Auto-generated method stub
		conn.setTypeMap(map);
	}

	@Override
	public void setHoldability(int holdability) throws SQLException {
		// TODO Auto-generated method stub
		conn.setHoldability(holdability);
	}

	@Override
	public int getHoldability() throws SQLException {
		// TODO Auto-generated method stub
		return conn.getHoldability();
	}

	@Override
	public Savepoint setSavepoint() throws SQLException {
		// TODO Auto-generated method stub
		return conn.setSavepoint();
	}

	@Override
	public Savepoint setSavepoint(String name) throws SQLException {
		// TODO Auto-generated method stub
		return conn.setSavepoint(name);
	}

	@Override
	public void rollback(Savepoint savepoint) throws SQLException {
		// TODO Auto-generated method stub
		conn.rollback(savepoint);
	}

	@Override
	public void releaseSavepoint(Savepoint savepoint) throws SQLException {
		// TODO Auto-generated method stub
	    conn.releaseSavepoint(savepoint);	
	}

	@Override
	public Statement createStatement(int resultSetType,
			int resultSetConcurrency, int resultSetHoldability)
			throws SQLException {
		// TODO Auto-generated method stub
		return conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
	}

	@Override
	public PreparedStatement prepareStatement(String sql, int resultSetType,
			int resultSetConcurrency, int resultSetHoldability)
			throws SQLException {
		// TODO Auto-generated method stub
		return conn.prepareStatement(sql, resultSetType, resultSetConcurrency,resultSetHoldability);
	}

	@Override
	public CallableStatement prepareCall(String sql, int resultSetType,
			int resultSetConcurrency, int resultSetHoldability)
			throws SQLException {
		// TODO Auto-generated method stub
		return conn.prepareCall( sql,  resultSetType,
				 resultSetConcurrency,  resultSetHoldability);
	}

	@Override
	public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
			throws SQLException {
		// TODO Auto-generated method stub
		return conn.prepareStatement( sql,  autoGeneratedKeys);
	}

	@Override
	public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
			throws SQLException {
		// TODO Auto-generated method stub
		return conn.prepareStatement( sql, columnIndexes);
	}

	@Override
	public PreparedStatement prepareStatement(String sql, String[] columnNames)
			throws SQLException {
		// TODO Auto-generated method stub
		return conn.prepareStatement( sql,  columnNames);
	}

	@Override
	public Clob createClob() throws SQLException {
		// TODO Auto-generated method stub
		return conn.createClob();
	}

	@Override
	public Blob createBlob() throws SQLException {
		// TODO Auto-generated method stub
		return conn.createBlob();
	}

	@Override
	public NClob createNClob() throws SQLException {
		// TODO Auto-generated method stub
		return conn.createNClob();
	}

	@Override
	public SQLXML createSQLXML() throws SQLException {
		// TODO Auto-generated method stub
		return conn.createSQLXML();
	}

	@Override
	public boolean isValid(int timeout) throws SQLException {
		// TODO Auto-generated method stub
		return conn.isValid(timeout);
	}

	@Override
	public void setClientInfo(String name, String value)
			throws SQLClientInfoException {
		// TODO Auto-generated method stub
		conn.setClientInfo(name, value);
	}

	@Override
	public void setClientInfo(Properties properties)
			throws SQLClientInfoException {
		// TODO Auto-generated method stub
		conn.setClientInfo(properties);
	}

	@Override
	public String getClientInfo(String name) throws SQLException {
		// TODO Auto-generated method stub
		return conn.getClientInfo(name);
	}

	@Override
	public Properties getClientInfo() throws SQLException {
		// TODO Auto-generated method stub
		return conn.getClientInfo();
	}

	@Override
	public Array createArrayOf(String typeName, Object[] elements)
			throws SQLException {
		// TODO Auto-generated method stub
		return conn.createArrayOf(typeName, elements);
	}

	@Override
	public Struct createStruct(String typeName, Object[] attributes)
			throws SQLException {
		// TODO Auto-generated method stub
		return conn.createStruct(typeName, attributes);
	}
	
	public Connection getConnection(){
		return this.conn;
	}
}

  注意看里面的close方法,和最后一个getConnection方法,getConnection方法是为了直观的观察数据库连接池里面对象的流转情况

然后在servlet里面调用并打印数据库连接池信息

package com.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.mysql.JDBC_POOL;
import com.mysql.myConnection;

public class getConnection extends HttpServlet {

	private static final long serialVersionUID = 1806541121588301641L;

	public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
         doPost(request,response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
          PrintWriter out = response.getWriter();
          try{
        	  Connection conn = new JDBC_POOL().getConnection();
        	  out.print(conn+" : " + conn.hashCode());
          }catch(Exception e){
        	  System.out.println(e.getMessage());
        	  e.printStackTrace();
          }finally{
        	 
          }
	}
}

  最后我们来看看效果

还有控制台打印的信息

创建了数据库连接 : com.mysql.jdbc.JDBC4Connection@66922804 : 1720854532
创建了数据库连接 : com.mysql.jdbc.JDBC4Connection@47124746 : 1192380230
创建了数据库连接 : com.mysql.jdbc.JDBC4Connection@26aae86e : 648734830
程序获取连接对象 : com.mysql.jdbc.JDBC4Connection@66922804

  再访问一次

 

创建了数据库连接 : com.mysql.jdbc.JDBC4Connection@66922804 : 1720854532
创建了数据库连接 : com.mysql.jdbc.JDBC4Connection@47124746 : 1192380230
创建了数据库连接 : com.mysql.jdbc.JDBC4Connection@26aae86e : 648734830
程序获取连接对象 : com.mysql.jdbc.JDBC4Connection@66922804
程序获取连接对象 : com.mysql.jdbc.JDBC4Connection@47124746

  第三次

 

创建了数据库连接 : com.mysql.jdbc.JDBC4Connection@66922804 : 1720854532
创建了数据库连接 : com.mysql.jdbc.JDBC4Connection@47124746 : 1192380230
创建了数据库连接 : com.mysql.jdbc.JDBC4Connection@26aae86e : 648734830
程序获取连接对象 : com.mysql.jdbc.JDBC4Connection@66922804
程序获取连接对象 : com.mysql.jdbc.JDBC4Connection@47124746
程序获取连接对象 : com.mysql.jdbc.JDBC4Connection@26aae86e

  好的这时候三个连接对象都取完了,我们来第四次访问

 

创建了数据库连接 : com.mysql.jdbc.JDBC4Connection@66922804 : 1720854532
创建了数据库连接 : com.mysql.jdbc.JDBC4Connection@47124746 : 1192380230
创建了数据库连接 : com.mysql.jdbc.JDBC4Connection@26aae86e : 648734830
程序获取连接对象 : com.mysql.jdbc.JDBC4Connection@66922804
程序获取连接对象 : com.mysql.jdbc.JDBC4Connection@47124746
程序获取连接对象 : com.mysql.jdbc.JDBC4Connection@26aae86e
连接池已经没有连接对象
java.lang.Exception: 连接池已经没有连接对象
	at com.mysql.JDBC_POOL.getConnection(JDBC_POOL.java:41)
	at com.servlet.getConnection.doPost(getConnection.java:26)
	at com.servlet.getConnection.doGet(getConnection.java:20)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Thread.java:619)

  到这里和预想的一样,在servlet中如果释放了数据库连接,则我们也可以看到连接还给连接池的信息,这里就不再赘述。

以上是关于自己实现的一个简单的数据库连接池的主要内容,如果未能解决你的问题,请参考以下文章

java简单实现数据库连接池

一个简易的 MySQL 连接池实现

个人总结-3-连接池学习

基于UniDac的数据库连接池

半同步/半异步进程池实现流程

Druid连接池简单配置