【Java EE 学习 16 上】【dbcp数据库连接池】【c3p0数据库连接池】
一、回顾之前使用的动态代理的方式实现的数据库连接池:
代码:
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包
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.依赖包下载
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数据库连接池】的更多相关文章
- 【Java EE 学习 80 上】【WebService】
一.WebService概述 什么是WebService,顾名思义,就是基于Web的服务,它使用Http方式接收和响应外部系统的某种请求,从而实现远程调用.WebService实际上就是依据某些标准, ...
- 【Java EE 学习 74 上】【数据采集系统第六天】【使用Jfreechart的统计图实现】【Jfreechart的基本使用方法】
之前已经实现了数据的采集,现在已经有了基本的数据,下一步就需要使用这些数据实现统计图的绘制了.这里使用Jfreechart实现这些统计图的绘制.首先看一下Jfreechart的基本用法,只有知道了它的 ...
- 【Java EE 学习 17 上】【dbutils和回调函数】
一.dbutils的核心就是回调函数,可以说如果没有回调函数的思想,dbutils是不可能被开发出来的. 对于dbutils中的QuryRunner类,向该类的query方法提供不同的参数,可以得到不 ...
- 【Java EE 学习 76 上】【数据采集系统第八天】【角色授权】【用户授权】【权限的粗粒度控制】【权限的细粒度控制】
一.角色管理 单击导航栏上的"角色管理"超链接,跳转到角色管理界面,在该界面上显示所有角色,并提供角色的增加和删除.修改超链接. 1.增加新角色(角色授权) 流程:单击增加新角色超 ...
- 【Java EE 学习 25 上】【网上图书商城项目实战】
一.概述 1.使用的jdk版本:1.6 2.java EE版本:1.6 3.指导老师:传智播客 王建 二.小项目已经实现的功能 普通用户: 1.登陆 2.注册 3.购物 4.浏览 管理员用户(全部管理 ...
- 【Java EE 学习 16 下】【dbutils的使用方法】
一.为什么要使用dbutils 使用dbutils可以极大程度的简化代码书写,使得开发进度更快,效率更高 二.dbutils下载地址 http://commons.apache.org/proper/ ...
- 【Java EE 学习 67 上】【OA项目练习】【JBPM工作流的使用】
OA项目中有极大可能性使用到JBPM框架解决流程控制问题,比如请假流程.报销流程等等. JBPM:JBoss Business Process Management,翻译过来就是业务流程管理.实际上就 ...
- 【Java EE 学习 83 上】【SpringMVC】【基本使用方法】
一.SpringMVC框架概述 什么是SpringMVC?SpringMVC是一个和Struts2差不多的东西,他们的作用和性质几乎是相同的,甚至开发效率上也差不多,但是在运行效率上SpringMVC ...
- 【Java EE 学习 82 上】【MAVEN基本安装和使用方法】
一.Maven概述 1.什么是Maven? Maven中文意思是"行家"."专家",它是一种跨平台的项目管理工具. 2.Maven有什么作用? Maven能够实 ...
随机推荐
- ASP.NET Identity 简介
翻译自:http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity ,略有改动. 背景:A ...
- U盘启动 WinPE系统维护工具 任意安装GHO/WIM/ESD系统映像 无广告专业版
WinPE系统维护工具简介: 1.工具箱基于Windows 8 64位系统制作. 2.强大的DG分区工具专业版4.9.1(DOS版为4.9.0). 3.破解windows密码工具. 4.硬盘.内存检测 ...
- iOS播放器 - AVAudioPlayer
今天记录一下AVAudioPlayer,这个播放器类苹果提供了一些代理方法,主要用来播放本地音频. 其实也可以用来播放网络音频,只不过是将整个网络文件下载下来而已,在实际开发中会比较耗费流量不做推荐. ...
- Log4net中换行符
在log4net节点中 <appender name="DebugLogFileAppender" type="log4net.Appender.FileAppen ...
- Java并发编程之阻塞队列
1.什么是阻塞队列? 队列是一种数据结构,它有两个基本操作:在队列尾部加入一个元素,从队列头部移除一个元素.阻塞队里与普通的队列的区别在于,普通队列不会对当前线程产生阻塞,在面对类似消费者-生产者模型 ...
- CSS DIV自动适应高度
当div需要设定自适应高度时,可用到的css属性,min-height:200px;代表的是当div的内容超出了200px时,就会自动适应高度,兼容所有浏览器(IE6除外),如果是IE6则需要设置&q ...
- ElasticSearch-5.0安装head插件
环境 Windows10企业版X64 JDK-1.8 ElasticSearch-5.0.0 node-v4.5.0-x64.msi git客户端 步骤 安装node到D盘.如D:\nodejs. 把 ...
- Javascript实现前端简单路由
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http ...
- Google Maps API V3 之绘图库 信息窗口
Google官方教程: Google 地图 API V3 使用入门 Google 地图 API V3 针对移动设备进行开发 Google 地图 API V3 之事件 Google 地图 API V3 ...
- RAID技术介绍
RAID技术介绍 简介 RAID是一个我们经常能见到的名词.但却因为很少能在实际环境中体验,所以很难对其原理 能有很清楚的认识和掌握.本文将对RAID技术进行介绍和总结,以期能尽量阐明其概念. RAI ...