一、回顾之前使用的动态代理的方式实现的数据库连接池:

代码:

 package day16.utils;

 import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.Properties; public class JDBCUtils {
private static LinkedList<Connection>pool=new LinkedList<Connection>();//定义连接池,使用LinkedList能提高效率
static{
Properties properties=new Properties();
try {
properties.load(JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties"));
String driver=properties.getProperty("driver");
String username=properties.getProperty("username");
String password=properties.getProperty("password");
String url=properties.getProperty("url");
int connectionMaxNum=Integer.parseInt(properties.getProperty("connectionMaxNum"));
Class.forName(driver);
for(int i=0;i<connectionMaxNum;i++)
{
final Connection conn=DriverManager.getConnection(url, username, password);
//关键的一步:进行代理设置。
Object proxy=Proxy.newProxyInstance(
JDBCUtils.class.getClassLoader()
, new Class[]{Connection.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//如果调用了close方法,则不要关闭连接,而应当将连接回收。
if(method.getName().equals("close"))
{
synchronized(pool)
{
pool.addLast((Connection) proxy);//这里进行强制转换
System.out.println("调用了close方法!回收 "+proxy+" ,剩余连接数为"+pool.size());
pool.notify();//从等待池中唤醒任意一条线程
}
return null;//返回值是null表名拦截该方法的执行。这里的return位置非常重要,一不小心就会是的创建反射对象失败
}
//如果调用了其他的方法,则要放行
else
{
System.out.println("调用了 "+method.getName()+" 方法,放行!");
return method.invoke(conn, args);//注意这里的对象是conn,而不是其它对象
}
}
});
// System.out.println(proxy);
pool.addLast((Connection) proxy);//这里添加的一定是被代理的对象
}
System.out.println(pool);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
//获得连接对象的方法
public static Connection getConnection()
{
synchronized (pool) {
if(pool.size()==0)
{
System.out.println("连接池中没有可用连接,等待中------------");
try {
pool.wait();//等待的方式,使用的是pool*************************
} catch (InterruptedException e) {
e.printStackTrace();
}
return getConnection();//递归调用该方法目的是解锁之后重新获得连接
}
else
{
Connection conn=pool.removeFirst();
System.out.println("分配一条连接,剩余连接数目为"+pool.size());
return conn;
}
}
}
}

JDBCUtils.java

测试:

public void testByProxy() throws SQLException
{
Connection conn1=JDBCUtils.getConnection();
Connection conn2=JDBCUtils.getConnection();
Connection conn3=JDBCUtils.getConnection();
conn1.close();
Connection conn4=JDBCUtils.getConnection();
}

测试代码

运行结果:

调用了 toString 方法,放行!
调用了 toString 方法,放行!
调用了 toString 方法,放行!
[com.mysql.jdbc.JDBC4Connection@9c7650, com.mysql.jdbc.JDBC4Connection@1b9c3f, com.mysql.jdbc.JDBC4Connection@af28ad]
分配一条连接,剩余连接数目为2
分配一条连接,剩余连接数目为1
分配一条连接,剩余连接数目为0
调用了 toString 方法,放行!
调用了close方法!回收 com.mysql.jdbc.JDBC4Connection@9c7650 ,剩余连接数为1
分配一条连接,剩余连接数目为0

运行结果

和之前的相比有些改进:连接池使用LinkedList,效率更高。

功能增强的方式有两种:

  1.使用动态代理的方式

  2.使用包装的方式

实际上实现数据库连接池只需要实现一个接口:DataSource,然后改连接池就实现了标准化~

二、使用动态代理实现数据库连接池。

1.数据库连接池动态代理实现方式

package day16.utils;
//实现DataSource接口使用反射机制实现数据库连接池。
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.Properties;
import java.util.logging.Logger; import javax.sql.DataSource; public class DBCPPools implements DataSource{
private LinkedList<Connection>pools=new LinkedList<Connection>();
public DBCPPools()
{
try {
Properties config=new Properties();
config.load(DBCPPools.class.getClassLoader().getResourceAsStream("config.properties"));
Class.forName(config.getProperty("driver"));
String url=config.getProperty("url");
String username=config.getProperty("username");
String password=config.getProperty("password");
for(int i=0;i<3;i++)
{
final Connection conn=DriverManager.getConnection(url,username,password);
Object proxy=Proxy.newProxyInstance(
DBCPPools.class.getClassLoader(),
new Class[]{Connection.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().equals("close"))
{
synchronized(pools)
{
pools.addLast((Connection) proxy);
System.out.println("调用了close方法!回收 "+proxy+" ,剩余连接数为"+pools.size());
pools.notify();
}
return null;
}
else
{
// System.out.println(proxy(这里不能写上proxy,否则异常报出!!!!为什么????)+"调用了 "+method.getName()+" 方法,放行!");
System.out.println("调用了 "+method.getName()+" 方法,放行!");
return method.invoke(conn, args);
}
}
});
pools.add((Connection) proxy);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
//最重要的是实现这个方法。
@Override
public Connection getConnection(){
synchronized(pools)
{
if(pools.size()==0)
{
System.out.println("连接池中没有可用连接,等待中------------");
try {
pools.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
return getConnection();
}
else
{
Connection conn=pools.removeFirst();
System.out.println("分配一条连接,剩余连接数目为"+pools.size());
return conn;
}
}
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
return null;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}

DBCPPools.java

2.测试代码

public void testImplementsDataSourceInterfaceByProxy() throws SQLException
{
DBCPPools pool=new DBCPPools();
Connection conn1=pool.getConnection();
System.out.println(conn1);
System.out.println(); Connection conn2=pool.getConnection();
System.out.println(conn2);
System.out.println(); Connection conn3=pool.getConnection();
System.out.println(conn3);
System.out.println();
// conn1.close();//如果这里没有注释掉,则可以拿到第四条连接,连接池大小默认为3
Connection conn4=pool.getConnection();//第四条连接因为拿不到连接而进入等待池中。
System.out.println(conn4);
}

运行结果:

分配一条连接,剩余连接数目为2
调用了 toString 方法,放行!
com.mysql.jdbc.JDBC4Connection@46530 分配一条连接,剩余连接数目为1
调用了 toString 方法,放行!
com.mysql.jdbc.JDBC4Connection@8f5f75 分配一条连接,剩余连接数目为0
调用了 toString 方法,放行!
com.mysql.jdbc.JDBC4Connection@c3feb6 连接池中没有可用连接,等待中------------

将关闭连接的代码放开:

分配一条连接,剩余连接数目为2
调用了 toString 方法,放行!
com.mysql.jdbc.JDBC4Connection@912767 分配一条连接,剩余连接数目为1
调用了 toString 方法,放行!
com.mysql.jdbc.JDBC4Connection@1b1ebe5 分配一条连接,剩余连接数目为0
调用了 toString 方法,放行!
com.mysql.jdbc.JDBC4Connection@1f61490 调用了 toString 方法,放行!
调用了close方法!回收 com.mysql.jdbc.JDBC4Connection@912767 ,剩余连接数为1
分配一条连接,剩余连接数目为0
调用了 toString 方法,放行!
com.mysql.jdbc.JDBC4Connection@912767

三、使用包装的方法实现自定义数据库连接池

  1.包装对象:Connection类,这里作为数据库连接池的一个内部类(MyConnection)。

  2.使用包装的方法实现的数据库连接池:

 package day16.utils;

 import java.io.PrintWriter;
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.DriverManager;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.logging.Logger; import javax.sql.DataSource; //测试使用包装的方法定义一个数据库连接池
public class MyDBCPpool implements DataSource{
private LinkedList<Connection> pool =new LinkedList<Connection>();
public MyDBCPpool()
{
Properties properties=new Properties();
try {
properties.load(JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties"));
String driver=properties.getProperty("driver");
String username=properties.getProperty("username");
String password=properties.getProperty("password");
String url=properties.getProperty("url");
int connectionMaxNum=Integer.parseInt(properties.getProperty("connectionMaxNum"));
Class.forName(driver);
for(int i=0;i<connectionMaxNum;i++)
{
Connection conn=DriverManager.getConnection(url,username,password);
MyConnection connection =new MyConnection(conn);
pool.addLast(connection);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
@Override
public Connection getConnection() throws SQLException {
System.out.println(pool);
synchronized(pool)
{
if(pool.size()==0)
{
try {
pool.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
return getConnection();
}
else
{
Connection conn=pool.removeFirst();
System.out.println("分配出一条连接:"+conn+" 剩余"+pool.size()+" 条连接!");
return conn;
}
}
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
return null;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
// @Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
class MyConnection implements Connection
{
private Connection conn;
public MyConnection(Connection conn){
this.conn=conn;
}
//重写close方法
@Override
public void close() throws SQLException {
synchronized(pool)
{ pool.addLast(this);
            System.out.println(this+"还连接!剩余连接数:"+pool.size());
pool.notify();
}
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return conn.unwrap(iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return conn.isWrapperFor(iface);
}
@Override
public Statement createStatement() throws SQLException {
return conn.createStatement();
}
@Override
public PreparedStatement prepareStatement(String sql)
throws SQLException {
return conn.prepareStatement(sql);
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
return conn.prepareCall(sql);
}
@Override
public String nativeSQL(String sql) throws SQLException {
return conn.nativeSQL(sql);
}
@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
conn.setAutoCommit(autoCommit);
}
@Override
public boolean getAutoCommit() throws SQLException {
return conn.getAutoCommit();
}
@Override
public void commit() throws SQLException {
conn.commit();
}
@Override
public void rollback() throws SQLException {
conn.rollback();
}
@Override
public boolean isClosed() throws SQLException {
return conn.isClosed();
}
@Override
public DatabaseMetaData getMetaData() throws SQLException {
return conn.getMetaData();
}
@Override
public void setReadOnly(boolean readOnly) throws SQLException {
conn.setReadOnly(readOnly);
}
@Override
public boolean isReadOnly() throws SQLException {
return conn.isReadOnly();
}
@Override
public void setCatalog(String catalog) throws SQLException {
conn.setCatalog(catalog);
}
@Override
public String getCatalog() throws SQLException {
return conn.getCatalog();
}
@Override
public void setTransactionIsolation(int level) throws SQLException {
conn.setTransactionIsolation(level);
}
@Override
public int getTransactionIsolation() throws SQLException {
return conn.getTransactionIsolation();
}
@Override
public SQLWarning getWarnings() throws SQLException {
return conn.getWarnings();
}
@Override
public void clearWarnings() throws SQLException {
conn.clearWarnings();
}
@Override
public Statement createStatement(int resultSetType,
int resultSetConcurrency) throws SQLException {
return conn.createStatement(resultSetType, resultSetConcurrency);
}
@Override
public PreparedStatement prepareStatement(String sql,
int resultSetType, int resultSetConcurrency)
throws SQLException {
return conn.prepareStatement(sql, resultSetType, resultSetConcurrency);
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency) throws SQLException {
return conn.prepareCall(sql, resultSetType, resultSetConcurrency);
}
@Override
public Map<String, Class<?>> getTypeMap() throws SQLException {
return conn.getTypeMap();
}
@Override
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
conn.setTypeMap(map);
}
@Override
public void setHoldability(int holdability) throws SQLException {
conn.setHoldability(holdability);
}
@Override
public int getHoldability() throws SQLException {
return conn.getHoldability();
}
@Override
public Savepoint setSavepoint() throws SQLException {
return conn.setSavepoint();
}
@Override
public Savepoint setSavepoint(String name) throws SQLException {
return conn.setSavepoint(name);
}
@Override
public void rollback(Savepoint savepoint) throws SQLException {
conn.rollback(savepoint);
}
@Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
conn.releaseSavepoint(savepoint);
}
@Override
public Statement createStatement(int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
}
@Override
public PreparedStatement prepareStatement(String sql,
int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
return conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}
@Override
public PreparedStatement prepareStatement(String sql,
int autoGeneratedKeys) throws SQLException {
return conn.prepareStatement(sql, autoGeneratedKeys);
}
@Override
public PreparedStatement prepareStatement(String sql,
int[] columnIndexes) throws SQLException {
return conn.prepareStatement(sql, columnIndexes);
}
@Override
public PreparedStatement prepareStatement(String sql,
String[] columnNames) throws SQLException {
return conn.prepareStatement(sql, columnNames);
}
@Override
public Clob createClob() throws SQLException {
return conn.createClob();
}
@Override
public Blob createBlob() throws SQLException {
return conn.createBlob();
}
@Override
public NClob createNClob() throws SQLException {
return conn.createNClob();
}
@Override
public SQLXML createSQLXML() throws SQLException {
return conn.createSQLXML();
}
@Override
public boolean isValid(int timeout) throws SQLException {
return conn.isValid(timeout);
}
@Override
public void setClientInfo(String name, String value)
throws SQLClientInfoException {
conn.setClientInfo(name, value);
}
@Override
public void setClientInfo(Properties properties)
throws SQLClientInfoException {
conn.setClientInfo(properties);
}
@Override
public String getClientInfo(String name) throws SQLException {
return conn.getClientInfo(name);
}
@Override
public Properties getClientInfo() throws SQLException {
return conn.getClientInfo();
}
@Override
public Array createArrayOf(String typeName, Object[] elements)
throws SQLException {
return conn.createArrayOf(typeName, elements);
}
@Override
public Struct createStruct(String typeName, Object[] attributes)
throws SQLException {
return conn.createStruct(typeName, attributes);
}
@Override
public void setSchema(String schema) throws SQLException {
}
@Override
public String getSchema() throws SQLException {
return conn.getSchema();
}
@Override
public void abort(Executor executor) throws SQLException {
}
@Override
public void setNetworkTimeout(Executor executor, int milliseconds)
throws SQLException {
}
@Override
public int getNetworkTimeout() throws SQLException {
return conn.getNetworkTimeout();
}
}
}

  3.和之前的相比有哪些改动?

    (1)将数据库连接池的初始化放在了构造方法中。

    (2)连接池中放的是重写的Connection对象。

    (3)没有使用动态代理,效率更高。

    (4)将重写的Connection类放到了连接池类的内部作为内部类使用。

  4.测试代码

public void testMyDBCPpool() throws SQLException
{
MyDBCPpool pool=new MyDBCPpool();
Connection conn1=pool.getConnection();
System.out.println(conn1);
Connection conn2=pool.getConnection();
System.out.println(conn2);
Connection conn3=pool.getConnection();
System.out.println(conn3);
conn1.close();
Connection conn4=pool.getConnection();//第四条连接因为拿不到连接而进入等待池中。
System.out.println(conn4);
}

  5.运行结果:

[day16.utils.MyDBCPpool$MyConnection@13f7cd2, day16.utils.MyDBCPpool$MyConnection@11c0042, day16.utils.MyDBCPpool$MyConnection@154fe09]
分配出一条连接:day16.utils.MyDBCPpool$MyConnection@13f7cd2 剩余2 条连接!
day16.utils.MyDBCPpool$MyConnection@13f7cd2
[day16.utils.MyDBCPpool$MyConnection@11c0042, day16.utils.MyDBCPpool$MyConnection@154fe09]
分配出一条连接:day16.utils.MyDBCPpool$MyConnection@11c0042 剩余1 条连接!
day16.utils.MyDBCPpool$MyConnection@11c0042
[day16.utils.MyDBCPpool$MyConnection@154fe09]
分配出一条连接:day16.utils.MyDBCPpool$MyConnection@154fe09 剩余0 条连接!
day16.utils.MyDBCPpool$MyConnection@154fe09
day16.utils.MyDBCPpool$MyConnection@13f7cd2还连接!剩余连接数:1
[day16.utils.MyDBCPpool$MyConnection@13f7cd2]
分配出一条连接:day16.utils.MyDBCPpool$MyConnection@13f7cd2 剩余0 条连接!
day16.utils.MyDBCPpool$MyConnection@13f7cd2

  分析和总结:实际上使用DBCP数据库连接池原理和这基本上差不多,所以该数据库连接池的名字为MyDBCPpool,下面开始进入正题。


 四、DBCP数据库连接池。

  1.需要的jar包

    commons-dbcp2-2.1.jar

    commons-logging-1.2.jar

    commons-pool2-2.4.1.jar

  2.数据源类:

   org.apache.commons.dbcp2.BasicDataSource,但是获取连接的时候使用的是

     org.apache.commons.dbcp2.PoolingDataSource

   Connection类:PoolGuardConnectionWrapper是PoolingDataSource的内部类。

  3.是否回收连接到连接池

   代码追踪:

   PoolGuardConnectionWrapper的close方法:

   

   super.close()调用的并非是Connection类的方法,而是org.apache.commons.dbcp2.DelegatingConnection类的方法。

    

  closeInternal方法

    

  _conn.close()调用的是Connection接口的方法。

    

  可见实际上真的将连接关闭掉了,而非回收到了连接池中。

  4.使用dbcp线程池但是不使用自定义工具类

    4.1不使用配置文件

 public void testDBCP() throws SQLException
{
BasicDataSource bds=new BasicDataSource();
bds.setDriverClassName("com.mysql.jdbc.Driver");
bds.setUrl("jdbc:mysql://localhost:3306/bms");
bds.setUsername("root");
bds.setPassword("5a6f38");
// bds.setInitialSize(3);
bds.setMaxTotal(3);
Connection conn=bds.getConnection();
// System.out.println(conn.hashCode());
System.out.println(conn);
Connection conn1=bds.getConnection();
System.out.println(conn1);
// System.out.println(conn1.hashCode());
Connection conn2=bds.getConnection();
System.out.println(conn2);
// System.out.println(conn2.hashCode());
conn.close();
Connection conn3=bds.getConnection();
// System.out.println(conn3.hashCode());
System.out.println(conn3);
}

  运行结果:

25452873, URL=jdbc:mysql://localhost:3306/bms, UserName=root@localhost, MySQL-AB JDBC Driver
11678023, URL=jdbc:mysql://localhost:3306/bms, UserName=root@localhost, MySQL-AB JDBC Driver
8058664, URL=jdbc:mysql://localhost:3306/bms, UserName=root@localhost, MySQL-AB JDBC Driver
15102604, URL=jdbc:mysql://localhost:3306/bms, UserName=root@localhost, MySQL-AB JDBC Driver

  4.2使用配置文件(需要使用一个工厂类BasicDataSourceFactory)

username=root
password=5a6f38
url=jdbc:mysql://localhost:3306/test
driverClassName=com.mysql.jdbc.Driver
initialSize=3
maxTotal=3
#maxTotal的值默认是8,initialSize的值默认也是8

config_dbcp.properties

 public void testAutoConfigMethod()
{
try {
Properties properties=new Properties();
properties.load(Test2.class.getClassLoader().getResourceAsStream("config_dbcp.properties"));
DataSource ds=BasicDataSourceFactory.createDataSource(properties);
Connection conn=ds.getConnection();
System.out.println(conn);
Connection conn1=ds.getConnection();
System.out.println(conn1);
Connection conn2=ds.getConnection();
System.out.println(conn2);
System.out.println("关闭一条连接之后:");
conn.close();
for(int i=0;i<5;i++)
{
Connection c=ds.getConnection();
System.out.println(c);
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}

  在这里需要使用一个工厂类:BasicDataSourceFactory

  该工厂类可以根据配置文件创建一个数据源DataSource对象。

  5.定义工具类简化书写过程。

 package day16.regular.utils;

 import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp2.BasicDataSourceFactory; //使用第三方jar包创建dbcp连接池
public class DataSourceUtils_DBCP {
private DataSourceUtils_DBCP(){}//使用私有修饰构造方法,可以防止创建对象,这样可以确保只有一个DataSource对象
private static DataSource ds;
static
{
Properties properties=new Properties();
try {
properties.load(DataSourceUtils_DBCP.class.getClassLoader().getResourceAsStream("config_dbcp.properties"));
ds=BasicDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection()
{
Connection conn=null;
try {
conn=ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
public static DataSource getDataSource()
{
return ds;
}
}

五、c3p0数据库连接池。

  1.依赖包下载

  c3p0-0.9.5.jar

  mchange-commons-java-0.2.9.jar

  2.必须使用配置文件,名字必须为:c3p0-config.xml,位置必须在class路径下

 <?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- 默认配置,只可以出现一次 -->
<default-config>
<!-- 连接超时设置30秒 -->
<property name="checkoutTimeout">30000</property>
<!-- 30秒检查一次connection的空闲 -->
<property name="idleConnectionTestPeriod">30</property>
<!--初始化的池大小 -->
<property name="initialPoolSize">2</property>
<!-- 最多的一个connection空闲时间 -->
<property name="maxIdleTime">30</property>
<!-- 最多可以有多少个连接connection -->
<property name="maxPoolSize">10</property>
<!-- 最少的池中有几个连接 -->
<property name="minPoolSize">2</property>
<!-- 批处理的语句-->
<property name="maxStatements">50</property>
<!-- 每次增长几个连接 -->
<property name="acquireIncrement">3</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">
<![CDATA[jdbc:mysql://10.6.112.200:3306/test?useUnicode=true&characterEncoding=UTF-8]]>
</property>
<property name="user">root</property>
<property name="password">5a6f38</property>
</default-config> <named-config name="namedconfig">
<!-- 连接超时设置30秒 -->
<property name="checkoutTimeout">30000</property>
<!-- 30秒检查一次connection的空闲 -->
<property name="idleConnectionTestPeriod">30</property>
<!--初始化的池大小 -->
<property name="initialPoolSize">2</property>
<!-- 最多的一个connection空闲时间 -->
<property name="maxIdleTime">30</property>
<!-- 最多可以有多少个连接connection -->
<property name="maxPoolSize">2</property>
<!-- 最少的池中有几个连接 -->
<property name="minPoolSize">2</property>
<!-- 批处理的语句-->
<property name="maxStatements">50</property>
<!-- 每次增长几个连接 -->
<property name="acquireIncrement">2</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">
<![CDATA[jdbc:mysql://10.6.112.200:3306/test?useUnicode=true&characterEncoding=UTF-8]]>
</property>
<property name="user">root</property>
<property name="password">5a6f38</property>
</named-config>
</c3p0-config>

c3p0-config.xml

  3.使用的数据源类:com.mchange.v2.c3p0.ComboPooledDataSource

   使用的Connection类:com.mchange.v2.c3p0.impl.NewProxyConnection

  4.自定义工具类包装DataSource以简化书写

 package day16.regular.utils;
/**
* 使用c3p0创建的连接池。
*/
import java.sql.Connection;
import java.sql.SQLException; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; public class DataSourceUtils_C3P0 {
private static DataSource ds=null;
static{
ds=new ComboPooledDataSource("namedconfig");
}
public static Connection getConnection(){
Connection conn=null;
try {
conn=ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
public static DataSource getDataSource(){
return ds;
}
}

  5.测试代码

  假设数据库连接池中最多只能有两条连接。

 public void testC() throws SQLException
{
      private static DataSource ds=DataSourceUtils_C3P0.getDataSource();
Connection conn=ds.getConnection();
// NewProxyConnection a=null;
System.out.println(conn);
Connection conn1=ds.getConnection();
System.out.println(conn1); conn1.close();
Connection conn2=ds.getConnection();
System.out.println(conn2);
}

  6.运行结果:

连接池初始化信息略。
com.mchange.v2.c3p0.impl.NewProxyConnection@116d7bd [wrapping: com.mysql.jdbc.JDBC4Connection@ade3e9]
com.mchange.v2.c3p0.impl.NewProxyConnection@3337df [wrapping: com.mysql.jdbc.JDBC4Connection@9920f6]
com.mchange.v2.c3p0.impl.NewProxyConnection@1548499 [wrapping: com.mysql.jdbc.JDBC4Connection@9920f6]

  7.c3p0总结。

    (1)c3p0连接池中存放的是标准的Connection对象(实际上是JDBC4Connection对象),在分配的时候再对其进行包装。

    (2)调用close方法将会销毁NewProxyConnection对象,NewProxyConnection是Connection(JDBC4Connection)的包装类。

    (3)调用close方法不会销毁连接池中的对象。

  也就是说c3p0的管理方式类似于卖蛋糕,平时蛋糕放在柜台中,当客人明确了想要买某个蛋糕之后服务人员才对其进行包装。

【Java EE 学习 16 上】【dbcp数据库连接池】【c3p0数据库连接池】的更多相关文章

  1. 【Java EE 学习 80 上】【WebService】

    一.WebService概述 什么是WebService,顾名思义,就是基于Web的服务,它使用Http方式接收和响应外部系统的某种请求,从而实现远程调用.WebService实际上就是依据某些标准, ...

  2. 【Java EE 学习 74 上】【数据采集系统第六天】【使用Jfreechart的统计图实现】【Jfreechart的基本使用方法】

    之前已经实现了数据的采集,现在已经有了基本的数据,下一步就需要使用这些数据实现统计图的绘制了.这里使用Jfreechart实现这些统计图的绘制.首先看一下Jfreechart的基本用法,只有知道了它的 ...

  3. 【Java EE 学习 17 上】【dbutils和回调函数】

    一.dbutils的核心就是回调函数,可以说如果没有回调函数的思想,dbutils是不可能被开发出来的. 对于dbutils中的QuryRunner类,向该类的query方法提供不同的参数,可以得到不 ...

  4. 【Java EE 学习 76 上】【数据采集系统第八天】【角色授权】【用户授权】【权限的粗粒度控制】【权限的细粒度控制】

    一.角色管理 单击导航栏上的"角色管理"超链接,跳转到角色管理界面,在该界面上显示所有角色,并提供角色的增加和删除.修改超链接. 1.增加新角色(角色授权) 流程:单击增加新角色超 ...

  5. 【Java EE 学习 25 上】【网上图书商城项目实战】

    一.概述 1.使用的jdk版本:1.6 2.java EE版本:1.6 3.指导老师:传智播客 王建 二.小项目已经实现的功能 普通用户: 1.登陆 2.注册 3.购物 4.浏览 管理员用户(全部管理 ...

  6. 【Java EE 学习 16 下】【dbutils的使用方法】

    一.为什么要使用dbutils 使用dbutils可以极大程度的简化代码书写,使得开发进度更快,效率更高 二.dbutils下载地址 http://commons.apache.org/proper/ ...

  7. 【Java EE 学习 67 上】【OA项目练习】【JBPM工作流的使用】

    OA项目中有极大可能性使用到JBPM框架解决流程控制问题,比如请假流程.报销流程等等. JBPM:JBoss Business Process Management,翻译过来就是业务流程管理.实际上就 ...

  8. 【Java EE 学习 83 上】【SpringMVC】【基本使用方法】

    一.SpringMVC框架概述 什么是SpringMVC?SpringMVC是一个和Struts2差不多的东西,他们的作用和性质几乎是相同的,甚至开发效率上也差不多,但是在运行效率上SpringMVC ...

  9. 【Java EE 学习 82 上】【MAVEN基本安装和使用方法】

    一.Maven概述 1.什么是Maven? Maven中文意思是"行家"."专家",它是一种跨平台的项目管理工具. 2.Maven有什么作用? Maven能够实 ...

随机推荐

  1. jeecg单步调试

    自己没本事写开发平台,用别人的又各种担心,想学着别人弄个单步调试,老是出现这个"source not found"-- 百度各种方法都搞不定,担心是自己安装错了?这个jeecg本身 ...

  2. IE下a标签后面的span元素向右浮动后错位

    错误原因span放在了a标签之后 正确写法是放在之前 如下: <li><span>2016-07-29</span><a href="#" ...

  3. JS:offsetWidth\offsetleft 等图文解释

        网页可见区域宽: document.body.clientWidth;网页可见区域高: document.body.clientHeight;网页可见区域宽: document.body.of ...

  4. Android网络文件下载模块整理

    一.知识基础 tomcat服务器配置 理解http协议 理解javaIO操作相关知识 SDcard操作知识 Android 权限配置 二.实现步骤 1.从网上获取资源 public String do ...

  5. Java 内存管理

    java 内存管理机制 JAVA 内存管理总结 java 是如何管理内存的 Java 的内存管理就是对象的分配和释放问题.(两部分) 分配 :内存的分配是由程序完成的,程序员需要通过关键字 new 为 ...

  6. 各种HTTP状态的含义

    在网站建设的实际应用中,容易出现很多小小的失误,就像MySQL当初优化不到位,影响整体网站的浏览效果一样,其实,网站的常规http状态码的表现也是一样,Google无法验证网站几种解决办法,提及到由于 ...

  7. 关于linux asp.net MVC网站中 httpHandlers配置无效的处理方法

    近期有Jexus用户反映,在Linux ASP.NET MVC网站的Web.config中添加 httpHandlers 配置用于处理自定义类型,但是在运行中并没有产生预期的效果,服务器返回了404( ...

  8. PHP中判断变量为空的几种方法

    判断变量为空,在许多场合都会用到,同时自己和许多新手一样也经常会犯一些错误, 所以自己整理了一下PHP中一些常用的.判断变量为空的方法. 1. isset功能:判断变量是否被初始化本函数用来测试变量是 ...

  9. ThinkPHP 事务处理 (事务回滚) 、异常处理

    $tran_result = true;                $trans = M();                $trans->startTrans(); try {      ...

  10. 最终解决 mouseenter, mouseleave , mouseout mousehover mousemove等事件的区别?

    在jquery中, html页面的div的显示和隐藏, 修改等的功能, 最终都要由 事件 触发来引用, 不管是键盘事件, 还是鼠标事件... mouseenter和mouseleave是成对对应的, ...