- 浏览: 200439 次
- 性别:
- 来自: 紫禁城
文章分类
最新评论
-
a1439226817:
<!doctype html><html l ...
发布一个支持N级下拉列表联动的控件 -
a1439226817:
也不高个测试的demo,别人怎么用啊
发布一个支持N级下拉列表联动的控件 -
davaidgao:
不全啊,这是
Spring3.x权威开发指南 -
caizi12:
对于map绑定很是不方便,现在的做法,需要创建一User类,再 ...
浅谈 SpringMVC 数据绑定 -
joeyhuang:
不全啊..
Spring3.x权威开发指南
在前面的文章中已经说过使用连接池的很多好处和优势,也曾讨论过怎么使用数据库连接池,不过那时用的都是别人写好的一些DataSource类。现在我们自己来写一个数据库连接池,下面使用两种方法来实现,这里分别用到了两种设计模式,即Decorator(包装模式)和Proxy(代理模式)(关于其他的模式在后续的学习过程中都会一一介绍,敬请关注),首先来看第一种实现方法,也就是使用Decorator设计模式:
我们在这里引入一个ConnectionDecortor类,代码如下,此方法的功能不多介绍,看名字就知道是包装了Connection接口,对此接口的方法都做了简单的实现:
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Map;
public class ConnectionDecorator implements Connection {
Connection conn;
public ConnectionDecorator(Connection conn) {
this.conn = conn;
}
public Statement createStatement() throws SQLException {
return conn.createStatement();
}
public PreparedStatement prepareStatement(String arg0) throws SQLException {
return conn.prepareStatement(arg0);
}
public CallableStatement prepareCall(String arg0) throws SQLException {
return conn.prepareCall(arg0);
}
public String nativeSQL(String arg0) throws SQLException {
return conn.nativeSQL(arg0);
}
public void setAutoCommit(boolean arg0) throws SQLException {
conn.setAutoCommit(arg0);
}
public boolean getAutoCommit() throws SQLException {
return conn.getAutoCommit();
}
public void commit() throws SQLException {
conn.commit();
}
public void rollback() throws SQLException {
conn.rollback();
}
public void close() throws SQLException {
conn.close();
}
public boolean isClosed() throws SQLException {
return conn.isClosed();
}
public DatabaseMetaData getMetaData() throws SQLException {
return conn.getMetaData();
}
public void setReadOnly(boolean arg0) throws SQLException {
conn.setReadOnly(arg0);
}
public boolean isReadOnly() throws SQLException {
return conn.isReadOnly();
}
public void setCatalog(String arg0) throws SQLException {
conn.setCatalog(arg0);
}
public String getCatalog() throws SQLException {
return conn.getCatalog();
}
public void setTransactionIsolation(int arg0) throws SQLException {
conn.setTransactionIsolation(arg0);
}
public int getTransactionIsolation() throws SQLException {
return conn.getTransactionIsolation();
}
public SQLWarning getWarnings() throws SQLException {
return conn.getWarnings();
}
public void clearWarnings() throws SQLException {
conn.clearWarnings();
}
public Statement createStatement(int arg0, int arg1) throws SQLException {
return conn.createStatement(arg0, arg1);
}
public PreparedStatement prepareStatement(String arg0, int arg1, int arg2)
throws SQLException {
return conn.prepareStatement(arg0, arg1, arg2);
}
public CallableStatement prepareCall(String arg0, int arg1, int arg2)
throws SQLException {
return conn.prepareCall(arg0, arg1, arg2);
}
public Map<String, Class<?>> getTypeMap() throws SQLException {
return conn.getTypeMap();
}
public void setTypeMap(Map<String, Class<?>> arg0) throws SQLException {
conn.setTypeMap(arg0);
}
public void setHoldability(int arg0) throws SQLException {
conn.setHoldability(arg0);
}
public int getHoldability() throws SQLException {
return conn.getHoldability();
}
public Savepoint setSavepoint() throws SQLException {
return conn.setSavepoint();
}
public Savepoint setSavepoint(String arg0) throws SQLException {
return conn.setSavepoint(arg0);
}
public void rollback(Savepoint arg0) throws SQLException {
conn.rollback(arg0);
}
public void releaseSavepoint(Savepoint arg0) throws SQLException {
conn.releaseSavepoint(arg0);
}
public Statement createStatement(int arg0, int arg1, int arg2)
throws SQLException {
return conn.createStatement(arg0, arg1, arg2);
}
public PreparedStatement prepareStatement(String arg0, int arg1, int arg2,
int arg3) throws SQLException {
return conn.prepareStatement(arg0, arg1, arg2, arg3);
}
public CallableStatement prepareCall(String arg0, int arg1, int arg2,
int arg3) throws SQLException {
return conn.prepareCall(arg0, arg1, arg2);
}
public PreparedStatement prepareStatement(String arg0, int arg1)
throws SQLException {
return conn.prepareStatement(arg0, arg1);
}
public PreparedStatement prepareStatement(String arg0, int[] arg1)
throws SQLException {
return conn.prepareStatement(arg0, arg1);
}
public PreparedStatement prepareStatement(String arg0, String[] arg1)
throws SQLException {
return conn.prepareStatement(arg0, arg1);
}
}
从代码可以看出我们使用这个类只是对传入的Connection加上了一个外壳。
定义一个接口ConnectionPool,此接口只有两个方法,即getConnection()和releaseConnection():
import java.sql.Connection;
import java.sql.SQLException;
public interface ConnectionPool {
Connection getConnection() throws SQLException;
void releaseConnection(Connection conn);
}
下面DBConnectionPool类是对上面接口的实现:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Vector;
public class DBConnectionPool implements ConnectionPool {
//一个存储连接对象的集合,即上面所谓的连接池
private static Vector<Connection> pool;
//最多建立20个连接
private final int POOL_MAX_SIZE = 20;
//根据连接池中是否有连接对象来进行处理
public synchronized Connection getConnection() throws SQLException {
if (pool == null)
pool = new Vector<Connection>();
Connection conn = null;
//如果没有连接对象则新建一个
if (pool.isEmpty())
conn = createConnection();
else {
//如果有连接对象则取一个出来返回给客户端
int last_idx = pool.size() - 1;
conn = pool.get(last_idx);
pool.remove(pool.get(last_idx));
}
return new PooledConnection(this,conn);
}
public synchronized void releaseConnection(Connection conn) {
if (conn instanceof PooledConnection && pool.size() > POOL_MAX_SIZE) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
} else {
pool.add(conn);
}
}
//创建连接的方法
private Connection createConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql:///Student", "root", "");
return conn;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
}
下面的PooledConnection类中我们会对包装类ConnectionDecorator的close()方法做了一些特殊的处理,并不是直接关闭它,而是交给ConnectionPool 的 releaseConnection()去处理。
import java.sql.Connection;
import java.sql.SQLException;
public class PooledConnection extends ConnectionDecorator implements Connection {
private ConnectionPool connPool;
public PooledConnection(ConnectionPool connPool, Connection conn) {
super(conn);
this.connPool = connPool;
}
public void close() throws SQLException{
connPool.releaseConnection(this.conn);
}
}
至此第一种方法就实现了。下面来看第二种方法,即使用Proxy模式来实现:
ConnectionHandler 实现jdk提供的InvocationHandler 接口,重写了invoke方法。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
public class ConnectionHandler implements InvocationHandler {
Connection conn;
ConnectionPool pool;
public ConnectionHandler(ConnectionPool pool) {
this.pool = pool;
}
//bind方法是将动态代理绑定到指定的Connection。返回一个绑定代理后的Connection
public Connection bind(Connection conn) {
this.conn = conn;
Connection proxyConn = (Connection) Proxy.newProxyInstance(conn
.getClass().getClassLoader(), conn.getClass().getInterfaces(),
this);
return proxyConn;
}
//方法拦截器,判断当前调用的方法是否“close”方法,是则调用ConnectionPool的releaseConnection()方法
//否则直接调用Connection的方法。
public Object invoke(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
Object object = null;
if ("close".equals(arg1.getName())) {
pool.releaseConnection(conn);
} else {
object = arg1.invoke(conn, arg2);
}
return object;
}
}
然后把上面的DBConnectionPool.getConnection()方法做一点小小的修改:
//此方法返回值为一个经过绑定的连接
public synchronized Connection getConnection() throws SQLException {
if (pool == null)
pool = new Vector<Connection>();
Connection conn = null;
if (pool.isEmpty())
conn = createConnection();
else {
int last_idx = pool.size() - 1;
conn = pool.get(last_idx);
pool.remove(pool.get(last_idx));
}
ConnectionHandler handler = new ConnectionHandler(this);
return handler.bind(conn);
}
可以看出,基于Proxy模式的实现相对于Decorator模式的更加简洁了。
发表评论
-
Ubuntu下JDK+Tomcat+MySql环境的搭建
2011-06-15 14:48 1124Ubuntu 下 JDK+Tomcat+MySql ... -
Eclipse下切换 SVN 中已经保存的用户名和密码
2009-09-22 10:28 17041. 把 C:\Documents and Set ... -
Java实现汉字转换为拼音
2006-10-31 13:15 595import java.util.HashMap;import ... -
Java中的克隆(Clone)机制
2007-08-03 09:03 614现在Clone已经不是一个新鲜词语了,伴随着“多莉”的产生这个 ... -
JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用简介
2008-12-16 10:32 711在多线程大师Doug Lea的贡献下,在JDK1.5中加入 ... -
Java读取Properties文件的六种方法
2009-04-16 09:34 705使用J2SE API读取Properties文件的六种方法 ... -
深入探讨java集合类
2006-08-24 20:47 694不同的集合在添加对象时的处理是不同的:Set:不允许重复,且没 ... -
递归在java语言中的应用
2006-08-25 09:21 1012一 . 两个小经验 1.在定义一个类时,不要随意定义成员变量 ... -
java类装载器
2006-08-25 18:36 839一 . 面向接口编程. 不要面向类编程. 二 . 关于异常:如 ... -
几个Java基础知识
2006-08-25 19:18 654一 . Hashtable和HashMap Hashtab ... -
面向方面的编程(AOP)
2006-08-25 19:33 710面向对象的编程(OOP)中 ... -
Collection与UML学习
2006-09-01 19:19 675一 . 属性<property>时须注意:1. & ... -
反射和代理
2006-09-01 19:23 691一. 关于数据库.当今的数据处理大致可以分成两大类:联机事务处 ... -
Jdk1.5的新语法和一些java学习的小知识点
2006-09-01 19:30 1199一.1. 操作系统执行具体 ... -
使用DatabaseMetaData和ResultSetMetaData查看数据库信息
2006-10-07 22:26 927/**DatabaseMetaData接口查看数据库的整体综合 ... -
BASE64编码
2006-10-24 08:39 12971.HttpServletRequest: 请求 ... -
一个实现MD5的简洁的java类
2006-10-28 22:27 631一个实现MD5的简洁的java类 package test; ... -
使用Java将Word转为Html或txt!
2006-10-31 13:47 1201package org.client; // 使用Java将W ... -
理解接口
2006-11-01 14:12 522... -
正则表达式中问号等特殊字符的转义
2006-11-10 00:26 2462正则表达式中问号等特殊字符的转义 除 .$ ^ { [ ( | ...
相关推荐
对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,实现数据库连接池技术。某一应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源。 在较为完备的数据库连接池实现中,可根据...
C# 数据库连接池 C# 数据库连接池 C# 数据库连接池 C# 数据库连接池
数据库连接池,一个是XML版读取属性文件,一个是普通的
* 数据库连接池特点: * 获取连接时不需要了解连接的名字,连接池内部维护连接的名字 * 支持多线程,保证获取到的连接一定是没有被其他线程正在使用 * 按需创建连接,可以创建多个连接,可以控制连接的数量 * 连接...
context.xml, 数据库连接池配置文
达梦7数据库连接池,jdbcDriver,达梦7数据库连接池,jdbcDriver,达梦7数据库连接池,jdbcDriver,达梦7数据库连接池,jdbcDriver,达梦7数据库连接池,jdbcDriver,达梦7数据库连接池,jdbcDriver,
java手写数据库连接池,使用maven构建,一共有四个类方法,一个是测试类,测试类使用三个线程去操数据库连接
数据库连接池的例子.doc数据库连接池的例子.doc数据库连接池的例子.doc
C#高效数据库连接池源码
Tomcat5的数据库连接池配置Tomcat5的数据库连接池配置Tomcat5的数据库连接池配置Tomcat5的数据库连接池配置Tomcat5的数据库连接池配置Tomcat5的数据库连接池配置Tomcat5的数据库连接池配置Tomcat5的数据库连接池配置...
提供了数据库连接池的驱动,分别有c3p0、druid、dbcp三种数据库连接池的驱动
最近写了一个数据库连接池,虽然比不上专业的连接池,但是比普通的jdbc高效,很适合初学者。源码有注释,还带有测试程序。
数据库连接池 数据库连接池 数据库连接池 数据库连接池
Druid为监控而生的数据库连接池,它是阿里巴巴开源平台上的一个项目。Druid是Java语言中最好的数据库连接池,Druid能够提供强大的监控和扩展功能.它可以替换DBCP和C3P0连接池。Druid提供了一个高效、功能强大、可...
这个文档详细讲述了mysql数据库连接池的配置以及数据库连接池的工作原理。
收集了常见的数据库连接jar包,包括oracle、mysql、sql server、db2、opta、dbcp连接池、c3p0连接池等等常见的数据库jar包,不断更新中。
发现csdn上的连接池都是配设xml的,就手写了一份数据库连接池(java),连接sqlserver,里面一共两个java代码,Conn类包含了Connection和标志位,myconnection包含了数据库连接池的使用:获取连接,增加连接,释放...
c#语言下,使用netcore2.1框架,调用netstandard数据库连接池组件
比较实用的几种数据库连接池详细配置,值得收藏
数据库连接池的基础学习,针对mysql数据库的数据库连接池在java中的具体实现及应用配置