- 浏览: 206719 次
- 性别:
- 来自: 紫禁城
文章分类
最新评论
-
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 1168Ubuntu 下 JDK+Tomcat+MySql ... -
Eclipse下切换 SVN 中已经保存的用户名和密码
2009-09-22 10:28 17391. 把 C:\Documents and Set ... -
Java实现汉字转换为拼音
2006-10-31 13:15 621import java.util.HashMap;import ... -
Java中的克隆(Clone)机制
2007-08-03 09:03 642现在Clone已经不是一个新鲜词语了,伴随着“多莉”的产生这个 ... -
JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用简介
2008-12-16 10:32 742在多线程大师Doug Lea的贡献下,在JDK1.5中加入 ... -
Java读取Properties文件的六种方法
2009-04-16 09:34 740使用J2SE API读取Properties文件的六种方法 ... -
深入探讨java集合类
2006-08-24 20:47 732不同的集合在添加对象时的处理是不同的:Set:不允许重复,且没 ... -
递归在java语言中的应用
2006-08-25 09:21 1040一 . 两个小经验 1.在定义一个类时,不要随意定义成员变量 ... -
java类装载器
2006-08-25 18:36 871一 . 面向接口编程. 不要面向类编程. 二 . 关于异常:如 ... -
几个Java基础知识
2006-08-25 19:18 684一 . Hashtable和HashMap Hashtab ... -
面向方面的编程(AOP)
2006-08-25 19:33 747面向对象的编程(OOP)中 ... -
Collection与UML学习
2006-09-01 19:19 708一 . 属性<property>时须注意:1. & ... -
反射和代理
2006-09-01 19:23 716一. 关于数据库.当今的数据处理大致可以分成两大类:联机事务处 ... -
Jdk1.5的新语法和一些java学习的小知识点
2006-09-01 19:30 1232一.1. 操作系统执行具体 ... -
使用DatabaseMetaData和ResultSetMetaData查看数据库信息
2006-10-07 22:26 950/**DatabaseMetaData接口查看数据库的整体综合 ... -
BASE64编码
2006-10-24 08:39 13271.HttpServletRequest: 请求 ... -
一个实现MD5的简洁的java类
2006-10-28 22:27 665一个实现MD5的简洁的java类 package test; ... -
使用Java将Word转为Html或txt!
2006-10-31 13:47 1234package org.client; // 使用Java将W ... -
理解接口
2006-11-01 14:12 554... -
正则表达式中问号等特殊字符的转义
2006-11-10 00:26 2497正则表达式中问号等特殊字符的转义 除 .$ ^ { [ ( | ...
相关推荐
在Java编程中,数据库连接池是一种管理数据库连接的机制,它允许程序重复使用...对于初学者而言,理解并动手实现一个简单的连接池有助于深入理解数据库连接池的工作原理,为进一步学习和使用更复杂的连接池库打下基础。
【标题】"自己动手模仿Hibernate写数据库框架"揭示了本次讨论的核心内容——尝试构建一个类似于Hibernate的数据库操作框架。Hibernate是一个流行的Java ORM(对象关系映射)框架,它简化了数据库与Java对象之间的...
【标题】"write-jdbc-deom"项目是一个实践性的示例,它展示了如何从零开始构建一个简单的数据库连接池,特别是在Java环境...这个项目为你提供了一个动手实践的机会,让你能够更好地掌握数据库连接池的核心概念和技术。
2. 连接池管理:为了提高效率和资源利用率,通常会使用连接池来管理数据库连接。连接池预先创建一定数量的连接,当应用程序需要时,可以从池中获取,使用完毕后归还。 3. SQL语言:学习基础的SQL语句,如SELECT用于...
2. 数据库连接:为了存储和管理书籍信息、用户数据、订单详情等,我们需要一个可靠的数据库系统。MySQL和SQL Server都是流行的数据库管理系统,各有优势。MySQL以其开源、高性能和易用性受到青睐,而SQL Server则在...
《自己动手写网络爬虫》是一本专注于网络爬虫技术的图书,旨在帮助读者深入理解爬虫的工作原理并掌握实际编写爬虫的技能。书中的光盘文件包含了各个章节的详细内容,使得学习过程更加全面且高效。标签“爬虫”明确了...
2. 数据库连接池:了解如何使用Apache的DBCP或C3P0等开源库实现数据库连接池,提高应用程序的性能和资源利用率。 3. SQL语言:复习基本的SQL操作,包括SELECT、INSERT、UPDATE和DELETE语句,以及如何创建、修改和...
在实际应用中,通常会使用连接池来管理数据库连接,以提高性能和效率。同时,密码应该加密存储,而不是明文保存在数据库中,这里是为了简化示例。另外,用户界面(UI)部分,即“登录界面”,通常由前端技术如HTML、...
此外,应遵循良好的编程习惯,如使用连接池、及时断开连接以及合理管理资源。 通过以上知识,你应该能够开始使用C#和PI-SDK进行基于PI的开发。记住,实践是最好的老师,所以动手尝试创建自己的应用程序并与PI系统...
### 自己动手写网络爬虫 #### 知识点一:网络爬虫基础概念与应用场景 - **定义**:网络爬虫(Web Crawler),又称网页蜘蛛、网络机器人,是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。 - **应用...
- 高级应用中,可以考虑使用连接池(如Apache Commons DBCP、C3P0或HikariCP)来管理数据库连接。 以上就是使用JDBC创建数据库的基本步骤。理解并熟练掌握这些步骤,有助于你在实际开发中更高效地进行数据库操作。...
其次,本章可能涵盖了连接池的概念,如Apache Commons DBCP或C3P0,它们能够有效地管理和复用数据库连接,提高应用性能,尤其是在高并发环境下。理解连接池的工作原理和配置方式,能够帮助开发者优化数据库资源的...
9. **连接池**:在实际应用中,为了提高性能和减少资源消耗,我们通常会使用连接池(如C3P0、HikariCP等),它们可以复用已建立的数据库连接,避免频繁创建和关闭连接。 10. **批处理**:JDBC还支持批处理,允许一...
4. 数据库连接池:在实际应用中,为了提高性能和资源管理,通常会使用数据库连接池,如C3P0、Apache DBCP或HikariCP等。连接池可以预先配置好一定数量的数据库连接,避免了频繁创建和关闭连接的开销。 5. JSP中的...
**六、数据库连接池** 1. **连接池原理**:预先创建并管理一定数量的数据库连接,应用程序需要时从池中获取,用完归还。 2. **常见连接池**:如C3P0、DBCP、Druid、HikariCP等,它们提供更高效的连接管理和资源利用...
10. 性能优化:包括合理的索引设计、查询优化、存储过程使用、批处理操作以及数据库连接池的利用,都是提升系统性能的关键。 通过《Visual C#.NET数据库开发经典案例解析》的学习,读者不仅可以掌握C#编程和数据库...
最后,数据库应用开发部分可能涵盖如何使用面向对象编程语言(如Java、C#)与数据库交互,理解JDBC或ODBC接口,以及如何使用数据库连接池和缓存技术提高应用程序性能。 在复习这些真题时,不仅要关注正确答案,更要...
总的来说,"企业级DB2数据库学习与认证"不仅涉及DB2的基础知识,还包括其在复杂企业环境中的应用和管理,以及如何通过IBM的认证考试来验证和提升自己的专业技能。对于想要在数据库领域深耕的人来说,这是一个非常有...
此外,教学还会涉及一些高级话题,如存储过程、触发器的使用,以及如何在VC++中实现数据库连接池,提高系统性能。对于大型项目,数据库设计和优化也是关键,教学会提供一些设计原则和性能调优的策略。 最后,实践是...
4. **连接管理**:如何建立数据库连接,管理连接池,处理连接断开和重新连接的情况。 5. **数据操作**:阐述如何执行SQL查询,插入、更新和删除数据,以及如何使用事务确保数据的一致性。 6. **数据绑定**:介绍...