来源:http://blog.itpub.net/29254281/viewspace-1064007/
DBCP连接池可以缓存PreparedStatement,本质上就是缓存游标。
一个SQL语句,无论是Insert,Update,Delete还是Select都是游标操作,只不过Select游标指向查询结果,而其余的指向修改的目标。
除了连接可以缓存,游标也是可以缓存的,主要是避免游标的反复创建。虽然Oracle对完全相同的SQL可以共享执行计划,但是也需要去共享池查询这个SQL的信息(该SQL的Hash值是否在共享池内)。缓存游标,则进一步优化,避免了反复查询共享池的操作(个人臆测).
首先,做一个实验,证明游标可以反复利用。
- --创建实验表
- create table t as select rownum r from dual connect by level<10;
- set serveroutput on
- declare
- cursor cur is select * from t;
- v_record t%rowtype;
- begin
- open cur;
- fetch cur into v_record;
- dbms_output.put_line(v_record.r);
- fetch cur into v_record;
- dbms_output.put_line(v_record.r);
- close cur;
- open cur;
- fetch cur into v_record;
- dbms_output.put_line(v_record.r);
- fetch cur into v_record;
- dbms_output.put_line(v_record.r);
- close cur;
- end;
- /
实验结果:
1
2
1
2
可以看到游标在关闭之后,可以重新打开。并且重新打开的游标,与前次打开的游标,在数据上没有任何关系。第一次读到2,重新打开之后,会从1开始,而不是从3开始。
这个代码如果在JAVA程序中,就是这个样子的。
- Class.forName("oracle.jdbc.OracleDriver");
- Connection conn = DriverManager.getConnection("jdbc:oracle:thin:127.0.0.1:1521:orcl", "edmond", "edmond");
- PreparedStatement cmd = conn.prepareStatement("select * from t");
- //第一次调用
- ResultSet rs = cmd.executeQuery();
- rs.next();
- System.out.println(rs.getString(1));
- rs.next();
- System.out.println(rs.getString(1));
- //第二次调用
- rs = cmd.executeQuery();
- rs.next();
- System.out.println(rs.getString(1));
- rs.next();
- System.out.println(rs.getString(1));
- cmd.close();
- conn.close();
值得注意的是,PreparedStatement就表示Oracle的游标,但是一旦PreparedStatement关闭,就无法重新打开。所以复用PreparedStatement只需要在关闭之前重新调用executeQuery方法即可。
如果连接池启动PoolPreparedStatements,则可能在每一个Connection的代理对象中,包括下面的结构
Map<STRING, List> poolPreparedStatements
其中Key是SQL语句或者SQL语句的Hash值,代理的Connection会根据SQL返回一个可用的prepareStatement;如果没有,则会创建新的prepareStatement对象。而这个返回的prepareStatement对象,也同样是代理对象。
因为在调用连接池返回的prepareStatement的close方法时,不会真正的close这个对象,因为这样就无法实现复用的效果。可能只是修改了这个对象的标志位,标明其可用。
可以想见 ds.getConnection()返回的Connection和PreparedStatement应该都是代理对象。
- private static void testDataSource() throws SQLException {
- BasicDataSource ds = new BasicDataSource();
- ds.setUrl("jdbc:oracle:thin:127.0.0.1:1521:orcl");
- ds.setUsername("edmond");
- ds.setPassword("edmond");
- ds.setPoolPreparedStatements(true);
- ds.setMaxOpenPreparedStatements(300);
- Connection conn = ds.getConnection();
- PreparedStatement cmd = conn.prepareStatement("select * from t");
- ResultSet rs = cmd.executeQuery();
- rs.next();
- System.out.println(rs.getString(1));
- rs.next();
- System.out.println(rs.getString(1));
- cmd.close();
- conn.close();
- }
并且MaxOpenPreparedStatements的设置应该小于Oracle的Open_Cursor的数值。
- public static void main(String[] args) throws ClassNotFoundException, SQLException {
- List<PreparedStatement> list = new ArrayList<PreparedStatement>();
- Class.forName("oracle.jdbc.OracleDriver");
- Connection conn = DriverManager.getConnection("jdbc:oracle:thin:127.0.0.1:1521:orcl", "edmond", "edmond");
- for (int i = 0; i < 305; i++) {
- PreparedStatement cmd = conn.prepareStatement("select * from t");
- ResultSet rs = cmd.executeQuery();
- rs.next();
- rs.close();
- rs = null;
- list.add(cmd);
- }
- conn.close();
- }
Exception in thread "main" java.sql.SQLException: ORA-00604: 递归 SQL 级别 1 出现错误
ORA-01000: 超出打开游标的最大数
ORA-00604: 递归 SQL 级别 1 出现错误
ORA-01000: 超出打开游标的最大数
ORA-01000: 超出打开游标的最大数
最终这个连接的游标超过Oracle的open_cursor数值(默认300),就会报错。
所以启用了PoolPreparedStatements,一定注意设置MaxOpenPreparedStatements小于Oracle Open_Cursor的数值。
相关推荐
### DBCP连接池优化详解 #### 一、引言 在现代软件开发中,数据库连接池技术的应用极为广泛,特别是在高并发环境下,它可以显著提高应用程序处理能力并降低数据库资源的消耗。Apache DBCP(Database Connection ...
连接池的性能优化涉及多方面,包括合理设定最大连接数、最小连接数、超时时间,以及根据应用负载调整预编译语句的数量。此外,还可以考虑使用连接池监控工具,如JMX,监控连接池的状态,以便及时调整参数。 总结来...
### DBCP(Database Connection Pool)数据库连接池详解 #### 一、简介 DBCP(Database Connection Pool)是一个开源的数据库连接池实现,它依赖于Apache Jakarta commons-pool对象池机制。DBCP允许应用程序直接...
JdbcTemplate 和 Druid 连接池是 ...Druid 提供的监控统计功能可以帮助开发者实时了解数据库连接池的状态,优化数据库性能。而 JdbcTemplate 则简化了 SQL 操作,降低了出错的可能性,提高了代码的可读性和可维护性。
总结,无论是Tomcat还是Resin,配置全局数据库连接池都是为了优化资源利用,提高系统效率。正确配置并理解连接池的参数对优化数据库性能至关重要。在实际项目中,应根据应用需求和服务器负载来调整这些参数,以达到...
总的来说,Druid连接池是现代Java应用中常用的数据库连接池实现之一,它提供了丰富的特性、高效的性能和灵活的配置选项,有助于提升应用的数据库操作性能和稳定性。在实际项目中,合理配置和使用Druid能帮助开发者更...
7. 开启PSCache:poolPreparedStatements属性设置为true时,Druid连接池可以开启PSCache功能,即连接上可以缓存PreparedStatements,以提高SQL执行效率。maxPoolPreparedStatementPerConnectionSize属性则用于限制每...
DBCP通过一个预分配的连接池来优化管理数据库连接,提高访问数据库的性能。配置DBCP需要了解一些核心参数,这些参数可以帮助开发者根据不同的应用场景调整连接池的行为,从而获得最佳的性能和资源利用效率。 在配置...
- **解决方案**: 启用 `filters` 参数中的 `stat`、`wall` 等监控过滤器,通过 Web 控制台或日志查看详细的连接池监控信息。例如,可以通过 `stat` 过滤器查看 SQL 执行统计信息,通过 `wall` 过滤器识别潜在的 SQL...
DBCP(Database Connection Pool)是Apache的一个...通过这些配置,开发者可以根据应用的需求调整连接池的大小、连接的生命周期以及连接的验证策略,从而优化数据库性能,防止资源浪费,并确保应用的稳定性和可靠性。
总结来说,Druid 数据库连接池提供了一套完整的解决方案,包括性能优化、连接管理和监控。其简单易用的配置、强大的功能和优秀的性能,使得它在 Java 开发中占据一席之地。了解并熟练掌握 Druid 的使用,对于提高...
Druid不仅提供了高效稳定的数据库连接管理,还提供了丰富的监控信息,便于我们了解数据库连接池的状态,及时发现和解决问题,从而优化应用性能。在实际开发中,可以根据项目需求调整各项参数,以达到最佳的性能表现...