【Java EE 学习 16 上】【dbcp数据库连接池】【c3p0数据库连接池】
分类:
IT文章
•
2022-02-24 22:09:45

一、回顾之前使用的动态代理的方式实现的数据库连接池:
代码:
1 package day16.utils;
2
3 import java.io.IOException;
4 import java.lang.reflect.InvocationHandler;
5 import java.lang.reflect.Method;
6 import java.lang.reflect.Proxy;
7 import java.sql.Connection;
8 import java.sql.DriverManager;
9 import java.sql.SQLException;
10 import java.util.LinkedList;
11 import java.util.Properties;
12
13 public class JDBCUtils {
14 private static LinkedList<Connection>pool=new LinkedList<Connection>();//定义连接池,使用LinkedList能提高效率
15 static{
16 Properties properties=new Properties();
17 try {
18 properties.load(JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties"));
19 String driver=properties.getProperty("driver");
20 String username=properties.getProperty("username");
21 String password=properties.getProperty("password");
22 String url=properties.getProperty("url");
23 int connectionMaxNum=Integer.parseInt(properties.getProperty("connectionMaxNum"));
24 Class.forName(driver);
25 for(int i=0;i<connectionMaxNum;i++)
26 {
27 final Connection conn=DriverManager.getConnection(url, username, password);
28 //关键的一步:进行代理设置。
29 Object proxy=Proxy.newProxyInstance(
30 JDBCUtils.class.getClassLoader()
31 , new Class[]{Connection.class},
32 new InvocationHandler() {
33 @Override
34 public Object invoke(Object proxy, Method method, Object[] args)
35 throws Throwable {
36 //如果调用了close方法,则不要关闭连接,而应当将连接回收。
37 if(method.getName().equals("close"))
38 {
39 synchronized(pool)
40 {
41 pool.addLast((Connection) proxy);//这里进行强制转换
42 System.out.println("调用了close方法!回收 "+proxy+" ,剩余连接数为"+pool.size());
43 pool.notify();//从等待池中唤醒任意一条线程
44 }
45 return null;//返回值是null表名拦截该方法的执行。这里的return位置非常重要,一不小心就会是的创建反射对象失败
46 }
47 //如果调用了其他的方法,则要放行
48 else
49 {
50 System.out.println("调用了 "+method.getName()+" 方法,放行!");
51 return method.invoke(conn, args);//注意这里的对象是conn,而不是其它对象
52 }
53 }
54 });
55 // System.out.println(proxy);
56 pool.addLast((Connection) proxy);//这里添加的一定是被代理的对象
57 }
58 System.out.println(pool);
59 } catch (IOException e) {
60 e.printStackTrace();
61 } catch (ClassNotFoundException e) {
62 e.printStackTrace();
63 } catch (SQLException e) {
64 e.printStackTrace();
65 }
66 }
67 //获得连接对象的方法
68 public static Connection getConnection()
69 {
70 synchronized (pool) {
71 if(pool.size()==0)
72 {
73 System.out.println("连接池中没有可用连接,等待中------------");
74 try {
75 pool.wait();//等待的方式,使用的是pool*************************
76 } catch (InterruptedException e) {
77 e.printStackTrace();
78 }
79 return getConnection();//递归调用该方法目的是解锁之后重新获得连接
80 }
81 else
82 {
83 Connection conn=pool.removeFirst();
84 System.out.println("分配一条连接,剩余连接数目为"+pool.size());
85 return conn;
86 }
87 }
88 }
89 }
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.使用包装的方法实现的数据库连接池:
1 package day16.utils;
2
3 import java.io.PrintWriter;
4 import java.sql.Array;
5 import java.sql.Blob;
6 import java.sql.CallableStatement;
7 import java.sql.Clob;
8 import java.sql.Connection;
9 import java.sql.DatabaseMetaData;
10 import java.sql.DriverManager;
11 import java.sql.NClob;
12 import java.sql.PreparedStatement;
13 import java.sql.SQLClientInfoException;
14 import java.sql.SQLException;
15 import java.sql.SQLFeatureNotSupportedException;
16 import java.sql.SQLWarning;
17 import java.sql.SQLXML;
18 import java.sql.Savepoint;
19 import java.sql.Statement;
20 import java.sql.Struct;
21 import java.util.LinkedList;
22 import java.util.Map;
23 import java.util.Properties;
24 import java.util.concurrent.Executor;
25 import java.util.logging.Logger;
26
27 import javax.sql.DataSource;
28
29 //测试使用包装的方法定义一个数据库连接池
30 public class MyDBCPpool implements DataSource{
31 private LinkedList<Connection> pool =new LinkedList<Connection>();
32 public MyDBCPpool()
33 {
34 Properties properties=new Properties();
35 try {
36 properties.load(JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties"));
37 String driver=properties.getProperty("driver");
38 String username=properties.getProperty("username");
39 String password=properties.getProperty("password");
40 String url=properties.getProperty("url");
41 int connectionMaxNum=Integer.parseInt(properties.getProperty("connectionMaxNum"));
42 Class.forName(driver);
43 for(int i=0;i<connectionMaxNum;i++)
44 {
45 Connection conn=DriverManager.getConnection(url,username,password);
46 MyConnection connection =new MyConnection(conn);
47 pool.addLast(connection);
48 }
49 }
50 catch(Exception e)
51 {
52 e.printStackTrace();
53 }
54 }
55 @Override
56 public Connection getConnection() throws SQLException {
57 System.out.println(pool);
58 synchronized(pool)
59 {
60 if(pool.size()==0)
61 {
62 try {
63 pool.wait();
64 } catch (InterruptedException e) {
65 e.printStackTrace();
66 }
67 return getConnection();
68 }
69 else
70 {
71 Connection conn=pool.removeFirst();
72 System.out.println("分配出一条连接:"+conn+" 剩余"+pool.size()+" 条连接!");
73 return conn;
74 }
75 }
76 }
77 @Override
78 public Connection getConnection(String username, String password)
79 throws SQLException {
80 return null;
81 }
82 @Override
83 public PrintWriter getLogWriter() throws SQLException {
84 return null;
85 }
86 @Override
87 public void setLogWriter(PrintWriter out) throws SQLException {
88 }
89 @Override
90 public void setLoginTimeout(int seconds) throws SQLException {
91 }
92 @Override
93 public int getLoginTimeout() throws SQLException {
94 return 0;
95 }
96 // @Override
97 public Logger getParentLogger() throws SQLFeatureNotSupportedException {
98 return null;
99 }
100 @Override
101 public <T> T unwrap(Class<T> iface) throws SQLException {
102 return null;
103 }
104 @Override
105 public boolean isWrapperFor(Class<?> iface) throws SQLException {
106 return false;
107 }
108 class MyConnection implements Connection
109 {
110 private Connection conn;
111 public MyConnection(Connection conn){
112 this.conn=conn;
113 }
114 //重写close方法
115 @Override
116 public void close() throws SQLException {
117 synchronized(pool)
118 {120 pool.addLast(this);
System.out.println(this+"还连接!剩余连接数:"+pool.size());
121 pool.notify();
122 }
123 }
124 @Override
125 public <T> T unwrap(Class<T> iface) throws SQLException {
126 return conn.unwrap(iface);
127 }
128 @Override
129 public boolean isWrapperFor(Class<?> iface) throws SQLException {
130 return conn.isWrapperFor(iface);
131 }
132 @Override
133 public Statement createStatement() throws SQLException {
134 return conn.createStatement();
135 }
136 @Override
137 public PreparedStatement prepareStatement(String sql)
138 throws SQLException {
139 return conn.prepareStatement(sql);
140 }
141 @Override
142 public CallableStatement prepareCall(String sql) throws SQLException {
143 return conn.prepareCall(sql);
144 }
145 @Override
146 public String nativeSQL(String sql) throws SQLException {
147 return conn.nativeSQL(sql);
148 }
149 @Override
150 public void setAutoCommit(boolean autoCommit) throws SQLException {
151 conn.setAutoCommit(autoCommit);
152 }
153 @Override
154 public boolean getAutoCommit() throws SQLException {
155 return conn.getAutoCommit();
156 }
157 @Override
158 public void commit() throws SQLException {
159 conn.commit();
160 }
161 @Override
162 public void rollback() throws SQLException {
163 conn.rollback();
164 }
165 @Override
166 public boolean isClosed() throws SQLException {
167 return conn.isClosed();
168 }
169 @Override
170 public DatabaseMetaData getMetaData() throws SQLException {
171 return conn.getMetaData();
172 }
173 @Override
174 public void setReadOnly(boolean readOnly) throws SQLException {
175 conn.setReadOnly(readOnly);
176 }
177 @Override
178 public boolean isReadOnly() throws SQLException {
179 return conn.isReadOnly();
180 }
181 @Override
182 public void setCatalog(String catalog) throws SQLException {
183 conn.setCatalog(catalog);
184 }
185 @Override
186 public String getCatalog() throws SQLException {
187 return conn.getCatalog();
188 }
189 @Override
190 public void setTransactionIsolation(int level) throws SQLException {
191 conn.setTransactionIsolation(level);
192 }
193 @Override
194 public int getTransactionIsolation() throws SQLException {
195 return conn.getTransactionIsolation();
196 }
197 @Override
198 public SQLWarning getWarnings() throws SQLException {
199 return conn.getWarnings();
200 }
201 @Override
202 public void clearWarnings() throws SQLException {
203 conn.clearWarnings();
204 }
205 @Override
206 public Statement createStatement(int resultSetType,
207 int resultSetConcurrency) throws SQLException {
208 return conn.createStatement(resultSetType, resultSetConcurrency);
209 }
210 @Override
211 public PreparedStatement prepareStatement(String sql,
212 int resultSetType, int resultSetConcurrency)
213 throws SQLException {
214 return conn.prepareStatement(sql, resultSetType, resultSetConcurrency);
215 }
216 @Override
217 public CallableStatement prepareCall(String sql, int resultSetType,
218 int resultSetConcurrency) throws SQLException {
219 return conn.prepareCall(sql, resultSetType, resultSetConcurrency);
220 }
221 @Override
222 public Map<String, Class<?>> getTypeMap() throws SQLException {
223 return conn.getTypeMap();
224 }
225 @Override
226 public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
227 conn.setTypeMap(map);
228 }
229 @Override
230 public void setHoldability(int holdability) throws SQLException {
231 conn.setHoldability(holdability);
232 }
233 @Override
234 public int getHoldability() throws SQLException {
235 return conn.getHoldability();
236 }
237 @Override
238 public Savepoint setSavepoint() throws SQLException {
239 return conn.setSavepoint();
240 }
241 @Override
242 public Savepoint setSavepoint(String name) throws SQLException {
243 return conn.setSavepoint(name);
244 }
245 @Override
246 public void rollback(Savepoint savepoint) throws SQLException {
247 conn.rollback(savepoint);
248 }
249 @Override
250 public void releaseSavepoint(Savepoint savepoint) throws SQLException {
251 conn.releaseSavepoint(savepoint);
252 }
253 @Override
254 public Statement createStatement(int resultSetType,
255 int resultSetConcurrency, int resultSetHoldability)
256 throws SQLException {
257 return conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
258 }
259 @Override
260 public PreparedStatement prepareStatement(String sql,
261 int resultSetType, int resultSetConcurrency,
262 int resultSetHoldability) throws SQLException {
263 return conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
264 }
265 @Override
266 public CallableStatement prepareCall(String sql, int resultSetType,
267 int resultSetConcurrency, int resultSetHoldability)
268 throws SQLException {
269 return conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
270 }
271 @Override
272 public PreparedStatement prepareStatement(String sql,
273 int autoGeneratedKeys) throws SQLException {
274 return conn.prepareStatement(sql, autoGeneratedKeys);
275 }
276 @Override
277 public PreparedStatement prepareStatement(String sql,
278 int[] columnIndexes) throws SQLException {
279 return conn.prepareStatement(sql, columnIndexes);
280 }
281 @Override
282 public PreparedStatement prepareStatement(String sql,
283 String[] columnNames) throws SQLException {
284 return conn.prepareStatement(sql, columnNames);
285 }
286 @Override
287 public Clob createClob() throws SQLException {
288 return conn.createClob();
289 }
290 @Override
291 public Blob createBlob() throws SQLException {
292 return conn.createBlob();
293 }
294 @Override
295 public NClob createNClob() throws SQLException {
296 return conn.createNClob();
297 }
298 @Override
299 public SQLXML createSQLXML() throws SQLException {
300 return conn.createSQLXML();
301 }
302 @Override
303 public boolean isValid(int timeout) throws SQLException {
304 return conn.isValid(timeout);
305 }
306 @Override
307 public void setClientInfo(String name, String value)
308 throws SQLClientInfoException {
309 conn.setClientInfo(name, value);
310 }
311 @Override
312 public void setClientInfo(Properties properties)
313 throws SQLClientInfoException {
314 conn.setClientInfo(properties);
315 }
316 @Override
317 public String getClientInfo(String name) throws SQLException {
318 return conn.getClientInfo(name);
319 }
320 @Override
321 public Properties getClientInfo() throws SQLException {
322 return conn.getClientInfo();
323 }
324 @Override
325 public Array createArrayOf(String typeName, Object[] elements)
326 throws SQLException {
327 return conn.createArrayOf(typeName, elements);
328 }
329 @Override
330 public Struct createStruct(String typeName, Object[] attributes)
331 throws SQLException {
332 return conn.createStruct(typeName, attributes);
333 }
334 @Override
335 public void setSchema(String schema) throws SQLException {
336 }
337 @Override
338 public String getSchema() throws SQLException {
339 return conn.getSchema();
340 }
341 @Override
342 public void abort(Executor executor) throws SQLException {
343 }
344 @Override
345 public void setNetworkTimeout(Executor executor, int milliseconds)
346 throws SQLException {
347 }
348 @Override
349 public int getNetworkTimeout() throws SQLException {
350 return conn.getNetworkTimeout();
351 }
352 }
353 }
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不使用配置文件
1 public void testDBCP() throws SQLException
2 {
3 BasicDataSource bds=new BasicDataSource();
4 bds.setDriverClassName("com.mysql.jdbc.Driver");
5 bds.setUrl("jdbc:mysql://localhost:3306/bms");
6 bds.setUsername("root");
7 bds.setPassword("5a6f38");
8 // bds.setInitialSize(3);
9 bds.setMaxTotal(3);
10 Connection conn=bds.getConnection();
11 // System.out.println(conn.hashCode());
12 System.out.println(conn);
13 Connection conn1=bds.getConnection();
14 System.out.println(conn1);
15 // System.out.println(conn1.hashCode());
16 Connection conn2=bds.getConnection();
17 System.out.println(conn2);
18 // System.out.println(conn2.hashCode());
19 conn.close();
20 Connection conn3=bds.getConnection();
21 // System.out.println(conn3.hashCode());
22 System.out.println(conn3);
23 }
运行结果:
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
1 public void testAutoConfigMethod()
2 {
3 try {
4 Properties properties=new Properties();
5 properties.load(Test2.class.getClassLoader().getResourceAsStream("config_dbcp.properties"));
6 DataSource ds=BasicDataSourceFactory.createDataSource(properties);
7 Connection conn=ds.getConnection();
8 System.out.println(conn);
9 Connection conn1=ds.getConnection();
10 System.out.println(conn1);
11 Connection conn2=ds.getConnection();
12 System.out.println(conn2);
13 System.out.println("关闭一条连接之后:");
14 conn.close();
15 for(int i=0;i<5;i++)
16 {
17 Connection c=ds.getConnection();
18 System.out.println(c);
19 }
20 } catch (IOException e) {
21 e.printStackTrace();
22 } catch (Exception e) {
23 e.printStackTrace();
24 }
25 }
1 package day16.regular.utils;
2
3 import java.io.IOException;
4 import java.sql.Connection;
5 import java.sql.SQLException;
6 import java.util.Properties;
7
8 import javax.sql.DataSource;
9
10 import org.apache.commons.dbcp2.BasicDataSourceFactory;
11
12
13 //使用第三方jar包创建dbcp连接池
14 public class DataSourceUtils_DBCP {
15 private DataSourceUtils_DBCP(){}//使用私有修饰构造方法,可以防止创建对象,这样可以确保只有一个DataSource对象
16 private static DataSource ds;
17 static
18 {
19 Properties properties=new Properties();
20 try {
21 properties.load(DataSourceUtils_DBCP.class.getClassLoader().getResourceAsStream("config_dbcp.properties"));
22 ds=BasicDataSourceFactory.createDataSource(properties);
23 } catch (IOException e) {
24 e.printStackTrace();
25 } catch (Exception e) {
26 e.printStackTrace();
27 }
28 }
29 public static Connection getConnection()
30 {
31 Connection conn=null;
32 try {
33 conn=ds.getConnection();
34 } catch (SQLException e) {
35 e.printStackTrace();
36 }
37 return conn;
38 }
39 public static DataSource getDataSource()
40 {
41 return ds;
42 }
43 }
1 <?xml version="1.0" encoding="UTF-8"?>
2 <c3p0-config>
3 <!-- 默认配置,只可以出现一次 -->
4 <default-config>
5 <!-- 连接超时设置30秒 -->
6 <property name="checkoutTimeout">30000</property>
7 <!-- 30秒检查一次connection的空闲 -->
8 <property name="idleConnectionTestPeriod">30</property>
9 <!--初始化的池大小 -->
10 <property name="initialPoolSize">2</property>
11 <!-- 最多的一个connection空闲时间 -->
12 <property name="maxIdleTime">30</property>
13 <!-- 最多可以有多少个连接connection -->
14 <property name="maxPoolSize">10</property>
15 <!-- 最少的池中有几个连接 -->
16 <property name="minPoolSize">2</property>
17 <!-- 批处理的语句-->
18 <property name="maxStatements">50</property>
19 <!-- 每次增长几个连接 -->
20 <property name="acquireIncrement">3</property>
21 <property name="driverClass">com.mysql.jdbc.Driver</property>
22 <property name="jdbcUrl">
23 <![CDATA[jdbc:mysql://10.6.112.200:3306/test?useUnicode=true&characterEncoding=UTF-8]]>
24 </property>
25 <property name="user">root</property>
26 <property name="password">5a6f38</property>
27 </default-config>
28
29 <named-config name="namedconfig">
30 <!-- 连接超时设置30秒 -->
31 <property name="checkoutTimeout">30000</property>
32 <!-- 30秒检查一次connection的空闲 -->
33 <property name="idleConnectionTestPeriod">30</property>
34 <!--初始化的池大小 -->
35 <property name="initialPoolSize">2</property>
36 <!-- 最多的一个connection空闲时间 -->
37 <property name="maxIdleTime">30</property>
38 <!-- 最多可以有多少个连接connection -->
39 <property name="maxPoolSize">2</property>
40 <!-- 最少的池中有几个连接 -->
41 <property name="minPoolSize">2</property>
42 <!-- 批处理的语句-->
43 <property name="maxStatements">50</property>
44 <!-- 每次增长几个连接 -->
45 <property name="acquireIncrement">2</property>
46 <property name="driverClass">com.mysql.jdbc.Driver</property>
47 <property name="jdbcUrl">
48 <![CDATA[jdbc:mysql://10.6.112.200:3306/test?useUnicode=true&characterEncoding=UTF-8]]>
49 </property>
50 <property name="user">root</property>
51 <property name="password">5a6f38</property>
52 </named-config>
53 </c3p0-config>
1 package day16.regular.utils;
2 /**
3 * 使用c3p0创建的连接池。
4 */
5 import java.sql.Connection;
6 import java.sql.SQLException;
7
8 import javax.sql.DataSource;
9
10 import com.mchange.v2.c3p0.ComboPooledDataSource;
11
12 public class DataSourceUtils_C3P0 {
13 private static DataSource ds=null;
14 static{
15 ds=new ComboPooledDataSource("namedconfig");
16 }
17 public static Connection getConnection(){
18 Connection conn=null;
19 try {
20 conn=ds.getConnection();
21 } catch (SQLException e) {
22 e.printStackTrace();
23 }
24 return conn;
25 }
26 public static DataSource getDataSource(){
27 return ds;
28 }
29 }
1 public void testC() throws SQLException
2 {
private static DataSource ds=DataSourceUtils_C3P0.getDataSource();
3 Connection conn=ds.getConnection();
4 // NewProxyConnection a=null;
5 System.out.println(conn);
6 Connection conn1=ds.getConnection();
7 System.out.println(conn1);
8
9 conn1.close();
10 Connection conn2=ds.getConnection();
11 System.out.println(conn2);
12 }
连接池初始化信息略。
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]