- 浏览: 2617835 次
- 性别:
- 来自: 小胖儿的大城
文章分类
最新评论
-
ni4wangba0:
ni4wangba0 写道亲测,算法有问题。对不起,其实是我自 ...
谈谈"求线段交点"的几种算法(js实现,完整版) -
ni4wangba0:
亲测,算法有问题。
谈谈"求线段交点"的几种算法(js实现,完整版) -
kers007:
苹果不让Webapp 在appstore 里发布,我不知道对 ...
苹果真的要在 AppStore 里封杀 WebApp 吗? -
striveandlive:
fins = js大牛
[原创]GT-Template, 一个超轻量级的js模板工具. -
AlwaysYang:
基础扎实的才能行走天下。
关于body的"大小"在ie和ff下的一些基础知识
对spring JdbcTemplate的一个扩展(使其支持单Connection).
不怕大家笑话,以前一直没怎么使用过spring jdbc template,
印象中只用过
public List queryForList(String sql, Object[] args)
public Map queryForMap(String sql, Object[] args)
和SqlFunction
在orm大行其道,spring诞生快一个实际的今天,再来探讨jdbc的一些封装实在不知道有没有意义.
不过还是想把刚刚弄出来的一点东西和大家分享.
看了一下 JdbcTemplate,
发现起核心是那几个 execute 方法.
而那几个execute方法的机构大概是这样(重点讨论Connection,所以其他地方从简)
当你要批量执行一些操作时(不是 每个操作使用不同的sql,或者是其他不适合 addBatch的情形).
如下:
此时,在内部实际上执行了,n次 getConnection,releaseConnection.
而这些操作,在很多时候,是可以通过一个Connection来完成的.
我的扩展就是实现了这个功能.
我们系统中,有大量的嵌套查询.使用该JdbcTemplatePlus的唯一Connection特性后,类似的操作速度提升明显.
(不过可能我们原先的做法不对,也许 spring内部已经实现这个机制了 这些我就不明白了,欢迎大家来指正)
我们原先的做法(伪代码):
在使用 JdbcTemplatePlus 代替 JdbcTemplate,并设置.setUseOneConnection(true)后,
耗时变为原先的1/8左右.
扩展的 JdbcTemplatePlus 代码如下,欢迎大家拍砖,挑错.
对 execute方法的修改如下:
把所有的 this.ativeJdbcExtractor换成 getNativeJdbcExtractor(), 这个是必须的 呵呵.
把所有 Connection con = DataSourceUtils.getConnection(getDataSource()); 换成
Connection con = tryGetConnection();
把所有 DataSourceUtils.releaseConnection(con, getDataSource()); 换成
tryReleaseConnection(con);
不怕大家笑话,以前一直没怎么使用过spring jdbc template,
印象中只用过
public List queryForList(String sql, Object[] args)
public Map queryForMap(String sql, Object[] args)
和SqlFunction
在orm大行其道,spring诞生快一个实际的今天,再来探讨jdbc的一些封装实在不知道有没有意义.
不过还是想把刚刚弄出来的一点东西和大家分享.
看了一下 JdbcTemplate,
发现起核心是那几个 execute 方法.
而那几个execute方法的机构大概是这样(重点讨论Connection,所以其他地方从简)
execute方法开始 Connection con = DataSourceUtils.getConnection(getDataSource()); // 做一些数据库操作 DataSourceUtils.releaseConnection(con, getDataSource()); execute方法结束
当你要批量执行一些操作时(不是 每个操作使用不同的sql,或者是其他不适合 addBatch的情形).
如下:
JdbcTemplate jdbcTemplate=new JdbcTemplate(ds); jdbcTemplate.query(sql_1, args_1,rch_1); jdbcTemplate.query(sql_2, args_2,rch_2); jdbcTemplate.query(sql_3, args_3,rch_3); jdbcTemplate.query(sql_4, args_4,rch_4); ......
此时,在内部实际上执行了,n次 getConnection,releaseConnection.
而这些操作,在很多时候,是可以通过一个Connection来完成的.
我的扩展就是实现了这个功能.
JdbcTemplatePlus jdbcTemplate=new JdbcTemplatePlus(ds); // 内部使用一个唯一的Connection jdbcTemplate.setUseOneConnection(true); jdbcTemplate.query(sql_1, args_1,rch_1); jdbcTemplate.query(sql_2, args_2,rch_2); jdbcTemplate.query(sql_3, args_3,rch_3); jdbcTemplate.query(sql_4, args_4,rch_4); ...... // 最后调用该方法 释放那个内部唯一的Connection // 虽然我在finalize 里调用了,不过finalize毕竟不是总能在正确的时间被正确的调用 jdbcTemplate.releaseConnection();
我们系统中,有大量的嵌套查询.使用该JdbcTemplatePlus的唯一Connection特性后,类似的操作速度提升明显.
(不过可能我们原先的做法不对,也许 spring内部已经实现这个机制了 这些我就不明白了,欢迎大家来指正)
我们原先的做法(伪代码):
public List queryNsubQueryUserList(Map param){ // 外层查询 final String bsql="select * from ......"; final JdbcTemplate jdbcTemplate=createJdbcTemplate(); // 子查询相关 final String subSql="select ............ "; final JdbcTemplate subJdbcTemplate=createJdbcTemplate(); List rslist=jdbcTemplate.query(bsql.toString(),sqlArg, new ResultSetHandler(){ public void processRow(ResultSet rs) throws SQLException { final 一个VO recordObj=new 一个VO(); // 子查询 subJdbcTemplate.query(subSql, subQueryArgs, new ResultSetHandler(){ public void processRow(ResultSet rs) throws SQLException { // 一些操作........ } } ); // 一些操作........ recordObj.setXXXXX(rs.getString("XXXXX")); ......... // 将记录放入集合 addRecord(recordObj); } } ); return rslist; } }
在使用 JdbcTemplatePlus 代替 JdbcTemplate,并设置.setUseOneConnection(true)后,
耗时变为原先的1/8左右.
扩展的 JdbcTemplatePlus 代码如下,欢迎大家拍砖,挑错.
对 execute方法的修改如下:
把所有的 this.ativeJdbcExtractor换成 getNativeJdbcExtractor(), 这个是必须的 呵呵.
把所有 Connection con = DataSourceUtils.getConnection(getDataSource()); 换成
Connection con = tryGetConnection();
把所有 DataSourceUtils.releaseConnection(con, getDataSource()); 换成
tryReleaseConnection(con);
package com.neusoft.tdframework.dao; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import javax.sql.DataSource; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.CallableStatementCallback; import org.springframework.jdbc.core.CallableStatementCreator; import org.springframework.jdbc.core.ConnectionCallback; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.ParameterDisposer; import org.springframework.jdbc.core.PreparedStatementCallback; import org.springframework.jdbc.core.PreparedStatementCreator; import org.springframework.jdbc.core.SqlProvider; import org.springframework.jdbc.core.StatementCallback; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.jdbc.support.JdbcUtils; import org.springframework.util.Assert; public class JdbcTemplatePlus extends JdbcTemplate { private Connection connection=null; private boolean useOneConnection=false; public JdbcTemplatePlus() { super(); } public JdbcTemplatePlus(DataSource dataSource) { super(dataSource); } public JdbcTemplatePlus(DataSource dataSource, boolean lazyInit) { super(dataSource,lazyInit); } private Connection tryGetConnection(){ if (useOneConnection){ if (connection==null){ connection= DataSourceUtils.getConnection(getDataSource()); } return connection; } return DataSourceUtils.getConnection(getDataSource()); } private void tryReleaseConnection(Connection con){ if (!useOneConnection){ DataSourceUtils.releaseConnection(con, getDataSource()); } } public Connection getConnection(){ return connection; } public void setConnection(Connection connection){ this.connection=connection; } public boolean isUseOneConnection() { return useOneConnection; } public void setUseOneConnection(boolean useOneConnection) { this.useOneConnection = useOneConnection; } public void releaseConnection(){ DataSourceUtils.releaseConnection(connection, getDataSource()); } // 不明白这个方法为什么spring不把他弄成 protected 或 public, // 导致我要重写execute方法时还必须要重写这个方法 :( public static String getSql(Object sqlProvider) { if (sqlProvider instanceof SqlProvider) { return ((SqlProvider) sqlProvider).getSql(); } else { return null; } } /* 对 execute方法的修改如下: 把所有的 this.ativeJdbcExtractor换成 getNativeJdbcExtractor(), 这个是必须的 呵呵. 把所有 Connection con = DataSourceUtils.getConnection(getDataSource()); 换成 Connection con = tryGetConnection(); 把所有 DataSourceUtils.releaseConnection(con, getDataSource()); 换成 tryReleaseConnection(con); */ public Object execute(ConnectionCallback action) throws DataAccessException { Assert.notNull(action, "Callback object must not be null"); Connection con = tryGetConnection(); try { Connection conToUse = con; if (getNativeJdbcExtractor() != null) { conToUse = getNativeJdbcExtractor().getNativeConnection(con); } else { conToUse = createConnectionProxy(con); } return action.doInConnection(conToUse); } catch (SQLException ex) { tryReleaseConnection(con); con = null; throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex); } finally { tryReleaseConnection(con); } } public Object execute(StatementCallback action) throws DataAccessException { Assert.notNull(action, "Callback object must not be null"); Connection con = tryGetConnection(); Statement stmt = null; try { Connection conToUse = con; if (getNativeJdbcExtractor() != null && getNativeJdbcExtractor() .isNativeConnectionNecessaryForNativeStatements()) { conToUse = getNativeJdbcExtractor().getNativeConnection(con); } stmt = conToUse.createStatement(); applyStatementSettings(stmt); Statement stmtToUse = stmt; if (getNativeJdbcExtractor() != null) { stmtToUse = getNativeJdbcExtractor().getNativeStatement(stmt); } Object result = action.doInStatement(stmtToUse); handleWarnings(stmt.getWarnings()); return result; } catch (SQLException ex) { JdbcUtils.closeStatement(stmt); stmt = null; tryReleaseConnection(con); con = null; throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex); } finally { JdbcUtils.closeStatement(stmt); tryReleaseConnection(con); } } public Object execute(PreparedStatementCreator psc, PreparedStatementCallback action) throws DataAccessException { Assert.notNull(psc, "PreparedStatementCreator must not be null"); Assert.notNull(action, "Callback object must not be null"); if (logger.isDebugEnabled()) { String sql = getSql(psc); logger.debug("Executing prepared SQL statement" + (sql != null ? " [" + sql + "]" : "")); } Connection con = tryGetConnection(); PreparedStatement ps = null; try { Connection conToUse = con; if (getNativeJdbcExtractor() != null && getNativeJdbcExtractor() .isNativeConnectionNecessaryForNativePreparedStatements()) { conToUse = getNativeJdbcExtractor().getNativeConnection(con); } ps = psc.createPreparedStatement(conToUse); applyStatementSettings(ps); PreparedStatement psToUse = ps; if (getNativeJdbcExtractor() != null) { psToUse = getNativeJdbcExtractor() .getNativePreparedStatement(ps); } Object result = action.doInPreparedStatement(psToUse); handleWarnings(ps.getWarnings()); return result; } catch (SQLException ex) { if (psc instanceof ParameterDisposer) { ((ParameterDisposer) psc).cleanupParameters(); } String sql = getSql(psc); psc = null; JdbcUtils.closeStatement(ps); ps = null; tryReleaseConnection(con); con = null; throw getExceptionTranslator().translate( "PreparedStatementCallback", sql, ex); } finally { if (psc instanceof ParameterDisposer) { ((ParameterDisposer) psc).cleanupParameters(); } JdbcUtils.closeStatement(ps); tryReleaseConnection(con); } } public Object execute(CallableStatementCreator csc, CallableStatementCallback action) throws DataAccessException { Assert.notNull(csc, "CallableStatementCreator must not be null"); Assert.notNull(action, "Callback object must not be null"); if (logger.isDebugEnabled()) { String sql = getSql(csc); logger.debug("Calling stored procedure" + (sql != null ? " [" + sql + "]" : "")); } Connection con = tryGetConnection(); CallableStatement cs = null; try { Connection conToUse = con; if (getNativeJdbcExtractor() != null) { conToUse = getNativeJdbcExtractor().getNativeConnection(con); } cs = csc.createCallableStatement(conToUse); applyStatementSettings(cs); CallableStatement csToUse = cs; if (getNativeJdbcExtractor() != null) { csToUse = getNativeJdbcExtractor() .getNativeCallableStatement(cs); } Object result = action.doInCallableStatement(csToUse); handleWarnings(cs.getWarnings()); return result; } catch (SQLException ex) { // Release Connection early, to avoid potential connection pool // deadlock // in the case when the exception translator hasn't been initialized // yet. if (csc instanceof ParameterDisposer) { ((ParameterDisposer) csc).cleanupParameters(); } String sql = getSql(csc); csc = null; JdbcUtils.closeStatement(cs); cs = null; tryReleaseConnection(con); con = null; throw getExceptionTranslator().translate( "CallableStatementCallback", sql, ex); } finally { if (csc instanceof ParameterDisposer) { ((ParameterDisposer) csc).cleanupParameters(); } JdbcUtils.closeStatement(cs); tryReleaseConnection(con); } } protected void finalize() throws Throwable{ super.finalize(); releaseConnection(); } }
- JdbcTemplatePlus.rar (1.8 KB)
- 描述: 源码
- 下载次数: 402
评论
4 楼
airlulu
2007-08-20
JdbcTemplate之所以设计成只接收DataSource是跟Spring的事务同步机制有关。
如果在调用之前使用spring的编程或配置方式定义事务同步,就不会出现重复取连接的情况。
如果在调用之前使用spring的编程或配置方式定义事务同步,就不会出现重复取连接的情况。
3 楼
fins
2007-07-26
你可能用的是本地数据库吧??
在我们实际系统中,使用同一个 connection 确实要比在循环内部不停的去取得新connection快很多
当然这些与数据源的设置 网络情况 所使用的数据库等等有关.
在您的环境下也许确实提高不了速度.
在我们实际系统中,使用同一个 connection 确实要比在循环内部不停的去取得新connection快很多
当然这些与数据源的设置 网络情况 所使用的数据库等等有关.
在您的环境下也许确实提高不了速度.
2 楼
finly
2007-07-23
用了一下...感觉速度几乎没任何提升,我跟你的例子一样,也有一个子查询..用与没用花的时间都是40秒左右...看来只能换种查询方式了.
1 楼
downpour
2007-06-15
存在着一个问题,JDBCTemplate我们一般都是单例的,通过IoC注入到DAO中去,你现在继承JdbcTemplate去写,每次要用的时候就得自己去控制它的创建。你的这个思路好是好,不过总觉得还有一丝不足。
发表评论
-
一个商业公司如果要支持一个开源项目的话,它需要做哪些工作啊?
2009-12-07 16:55 5022一个商业公司如果要支持一个开源项目的话,它需要做哪些工作呢? ... -
如何让jxl (jexcelapi) 支持更多的数据
2009-01-08 23:52 4526jxl (jexcelapi) 一直是我比较喜欢的 java版 ... -
在java中"模拟" XMLHttpRequest
2008-11-03 12:17 13122这里所说的"模拟" 是指 : 在java中 ... -
利用google docs进行"轻量级过程管理".
2008-08-28 13:21 0利用google docs进行" ... -
[请教]jxl生成xls时,支持"合并"或"磁盘缓存"吗(导出大数据量时)
2008-07-28 09:37 6967jxl 由于其小巧 易用的特点, 逐渐已经取代了 POI-ex ... -
不错的国产开源免费的php框架: FleaPHP
2008-07-28 01:58 8532之前用他开发过一个小的网站 开发过程非常轻松愉快 体验也很好 ... -
GT-FrontController, 一个简陋的MVC控制器的设计思路
2008-07-06 23:53 2738在给GT-Grid做前后台结合的例子时, 为了"快速 ... -
h2database 普及系列一: 简介
2008-05-06 19:10 22139这不是一个新东西,但是 ... -
JSF 与 "我的伟大发明" ---- 关于B/S UI开发的胡言乱语
2008-04-10 14:25 14546这篇帖子后面的回复和 ... -
初看JSF后的胡言乱语
2008-04-10 09:31 4590最近看了一点jsf ---- 只 ... -
Help,如何在J2EE环境下使用Sqlite以及如何将sqlite打入war包
2008-03-27 09:46 3811需求是这样的 希望j2ee应用(基于应用 而不是整个服务器) ... -
请记住: i AM SoLiD. (关于View的事件触发顺序)
2007-11-16 04:11 2648View 提供了若干事件. 在渲染 布局 展现 相关事件的触 ... -
Android SDK下, 如何在程序中输出日志 以及如何查看日志.
2007-11-15 22:38 9854Android SDK下, 如何在程序中输出日志 以及如何查看 ... -
小胖加入Android Fans的 大军了 呵呵
2007-11-15 13:30 3161决定开始研究 Android 了. 以前研究过 j2me 对 ... -
老帖: findbugs简介
2007-11-02 10:09 3571这个时候说 findbugs ??? ... -
世上没有B/S系统,只有B系统和S系统.
2007-09-12 13:45 34445先说些与标题貌似无关的话. 随着prototype DWR ... -
[求助]有没有哪个缓存组件支持 基于访问频率的清理策略
2007-08-29 18:30 2413目前缓存清理策略几乎都是基于 存活期 和 活跃期 还有缓存队列 ... -
[发布2007-08-06]Ajax向导组件 WebWizard Component Beta1
2007-08-06 15:55 5007/****************************** ... -
寻求一个eclipse下更好的snippet插件(或代码模板管理插件 或代码生成器)
2007-07-26 11:12 4266eclipse自带一个snippet插件,但是功能有限. 只支 ... -
让Struts 1焕发青春----小议对Struts的改造.
2007-06-25 15:27 7617目前流行的新型的MVC框架 几乎都在"增强单元测试能 ...
相关推荐
JdbcTemplate是Spring提供的一个用于简化数据库操作的API,它是Spring对JDBC(Java Database Connectivity)的轻量级封装。通过使用JdbcTemplate,开发者可以避免编写大量的样板代码,如打开和关闭连接、处理结果集...
9.9.1. 对一个特定的 DataSource 使用了错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. 选择一...
Spring-JDBC是Spring框架的一个重要模块,它提供了一种简化数据库操作的抽象层,使得开发者可以更加方便地进行数据访问。在本篇文章中,我们将深入探讨Spring-JdbcTemplate、DataSourceTransactionManager以及相关的...
9.9.1. 对一个特定的 DataSource 使用错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. Spring JDBC包结构...
3. **NamedParameterJdbcTemplate**:这是JdbcTemplate的一个扩展,允许使用命名参数代替占位符,使得SQL语句更易读和维护。 4. **Transaction Management**:Spring提供了声明式事务管理,通过在方法上添加@...
9.9.1. 对一个特定的 DataSource 使用错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. Spring ...
9.9.1. 对一个特定的 DataSource 使用了错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. 选择一种...
9.9.1. 对一个特定的 DataSource 使用错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. Spring ...
JMS 1.1 是其一个重要版本,它提供了应用程序间的可靠通信,使得消息的生产者和消费者可以在不同的时间进行交互,即使它们可能同时处于运行状态或暂时离线。以下是对 JMS 1.1 规范中的关键知识点的详细解释: 1. **...
c3p0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。配置信息通常放在`jdbc.properties`文件中,包括数据库URL、用户名、密码以及连接池的相关参数。 **1.2 配置JdbcTemplate...
`JdbcTemplate`是Spring框架提供的一个用于简化JDBC编程的工具类,它封装了许多常用的数据库操作,如查询、更新等,并且通过模板模式设计,提供了灵活的扩展机制。这使得开发者能够更专注于业务逻辑而非繁琐的JDBC...
DataSource可以配置在应用服务器中,这样多个应用程序可以共享同一个数据源,减少了资源消耗。同时,应用服务器会负责管理这些连接,包括连接池的创建、连接的分配和释放,确保了高效且线程安全的数据库访问。 在...
- C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。 - C3P0的优势在于其内置的自动检测和修复损坏的连接功能,以及对多线程环境的良好支持。 - 配置C3P0的步骤与DBCP...
**Spring** 是一个开源的轻量级Java开发框架,主要用于简化企业级应用的开发过程。它最初由Rod Johnson创建,并于2004年首次发布。Spring框架的核心特性是**控制反转(Inversion of Control, IoC)**和**面向切面...
在本课程"02-01-11-基于Spring JDBC手写定制自己的ORM框架1"中,我们将探讨如何利用Spring的JdbcTemplate设计理念,来构建一个自定义的ORM(对象关系映射)框架。ORM框架的主要目的是简化Java应用程序与数据库之间的...
这里定义了一个名为`DynamicDataSource`的`Bean`,它能够根据传入的键值动态地选择数据源。 #### 5. jdbcTemplate配置 最后,还需要配置`jdbcTemplate`以供业务层调用。 ```xml <!-- jdbcTemplate配置 --> ...
在构建一个音乐网站平台系统的过程中,技术和工具的选择至关重要。在这个项目中,主要涉及了两个核心部分:数据爬取和后端服务的搭建。下面将详细阐述这两个方面。 首先,我们来看数据爬取部分,这里使用了`Jsoup`...
Java通过Druid连接MySQL是一种常见的数据库操作方式,Druid是一个强大的数据库连接池组件,由阿里巴巴开源,它提供了优秀的性能、全面的监控以及强大的扩展性。在这个场景中,我们将探讨如何在Java环境中使用Druid来...
Spatialite是一个开源的扩展,它为SQLite数据库添加了对地理空间数据的支持,使其能够处理复杂的地理空间操作。 首先,你需要确保在系统`system32`目录下已经安装并配置了Spatialite的相关库。通常,这包括`...
多对一关系是指多个实体对象与另一个实体对象之间存在关联关系。例如,一个订单可能属于一个客户,但一个客户可以拥有多个订单。在Hibernate中,可以通过`@ManyToOne`注解来定义这种关系。 **示例代码**: ```java...