04. 数据库连接池(DataSource)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据库连接池(DataSource)
1、概念
在三层架构中,DAO层直接与数据库交互,首先要建立与数据库的连接,如果采用下图(a)所示,则用户每次的请求都要创建连接,用完又关闭,而数据库连接的创建和关闭需要消耗较大的资源,因此实际开发中常采用图(b)所示,在应用程序启动时创建一个包含多个Connection对象的连接池,DAO层使用时直接从池子里取一个Connection对象,用完后放回池子,避免了重复创建关闭数据库连接造成的开销。
2、数据库连接池原理
下面的代码模拟了数据库连接池的原理(代码中的JDBCUtil工具类见《MySQL(JDBC)》),池子里保持了10个Connection对象,并提供了getConnection和release方法:
public class ConnectionPoolDemo {
//连接池实际上就是一个List
private static List
static{//加载连接池类时在池子中放入10个连接
for(int i = 0;i < 10;i ++){
Connection conn;
try {
conn = JDBCUtil.getConnection();
pool.add(conn);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//从池子中取出一个连接
public synchronized Connection getConnection(){
return pool.remove(0);
}
//把连接还回池子中
public static void release(Connection conn){
pool.add(conn);
}
}
3、编写一个符合规范的连接池
上节模拟数据库连接池原理的代码也实现了一个简单连接池,但是不符合规范(Sun公司制定)。编写一个符合规范的连接池需要实现javax.sql.DataSource接口。(DataSource接口中定义了两个重载的getConnection方法)
编程难点☆:当用户使用完Connection,执行conn.close()时,Connection对象应保证将自己还给连接池,而不要把conn关闭。之所由Connection对象保证将自己返回到LinkedList 中,是因为DataSource接口中并未定义上节例子中类似release的方法。所以必须改写Connection中的close方法,使得用户执行conn.close()时,将Connection对象还给连接池。解决方案☆:改写驱动程序中Connection类的close方法。对已知类的某些方法进行功能上的改变,有以下几种编码方案(☆):
1)编写子类,覆写需要改变的方法。此处行不通,原因有:①程序中不知道继承哪个驱动的Connection实现类②数据库驱动对Connection接口的实现类是final的,不允许被继承。
2)装饰(包装)设计模式(静态代理)
①定义包装类:MyConnection,该类完成了对com.mysql.jdbc.Connection类的包装。
关键词:保持被包装对象的原有信息、对某个/某些方法进行改写。包装类的编写过程如下:/**
* 目前要包装的类是:com.mysql.jdbc.Connection
* @author flyne
*/
//1、编写一个类,实现与被包装类相同的接口。
public class MyConnection implements Connection {
//2、定义一个变量,引用被包装类的实例(保持被包装对象的原有信息)
private Connection conn;
private List
//3、在构造方法中传入被包装类的实例
public MyConnection(Connection conn,List
this.pool = pool;
}
//4、对于需要改写的方法,编写自己的代码即可
public void close() throws SQLException {
pool.add(conn);
}
//5、对于不需要改写的方法,调用被包装对象的对应方法
public
return conn.unwrap(iface);
}
……//其他代码从略
}
②实现DataSource接口。
public class MyDataSource implements DataSource {
private static List
static{
try {
for(int i=0;i<10;i++){
Connection conn = JDBCUtil.getConnection();//创建的新连接
pool.add(conn);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public Connection getConnection() throws SQLException {