隔叶黄莺 The Blog of Unmi

〖隔叶黄莺三四声,挂壁飞瀑千万尘。若是人间无净土,此处为何妙语真! 隔叶黄莺四字,本非取自此句,而有寄寓他意,因见妙语,亦与予心合!〗

BlogJava 首页 新随笔 联系 聚合 管理
  243 Posts :: 87 Stories :: 600 Comments :: 0 Trackbacks
我在 Websphere Application Server (WAS) 下配置 JDBC 提供程序时,选择了 Oracle JDBC Driver 确定之后,看到最后一个选项是:oracle.jdbc.pool.OracleConnectionPoolDataSource。

顾名思义,这是一个 DataSource 实现为,就像 DBCP 的 BasicDataSource 一样。那么能不能也像 BasicDataSource 那样,通过 new BasicDataSource(),然后设置各个必须的属性得到一个数据源 DataSource 呢?这个 OracleConnectionPoolDataSource 又是在哪个包里呢?

用 Eclipse 的 Jar Search 插件一查,原来它就是我们熟知的 classes111.jar 里,当然,在 $ORACLE_HOME/jdbc/lib 下的 classes12.jar、classes12.zip、classes12dms.jar、classes111.zip, nls_charset11.jar、nls_charset11.zip、nls_charset12.jar、nls_charset12.zip、 ojdbc14.jar、ojdbc14_g.jar。它们都是可用的 Oracle 驱动包,只是一直都未搞明它们之间有什么或大或小的差异。

先看一段 DataSource 的创建及测试代码



测试过程及结果:运行上面的代码,确实能获得数据库表中的记录,并且 Connection 的实现类是 oracle.jdbc.driver.OracleConnection。我们可以通过设定断点在 main() 方法的第一个 conn.close() 代码行,进行单步调试。

这时我们在命令行下执行 netstat -na|findstr 38.2 查看到 38.2 的连接,发现该连接是 ESTABLISHED

执行 conn.close() 方法,再用上面的 netstat 命令,看到上一个连接是 TIME_WAIT
再执行 conn = ds.getConnection(); netstat 看到又新启了一个连接 ESTABLISHED
再执行 conn.close(),上面连接变为 TIME_WAIT

注:短时间内,根据目标地址加端口号可唯一确定是否同一连接

由此我们可以断定,我们拿到的数据库的连接并没有被池化,有点是为 OracleConnectionPoolDataSource 所迷惑了。每次取的都是新的连接,因为在 conn.close() 是实际关闭了物理连接,连接无法被重用。

那么怎么才能让连接池化可重复利用呢?我们要引入 OracleConnectionCacheImpl,也是在 classes111.jar 中有,和 OracleConnectionPoolDataSource 一样都实现了 DataSource 接口。

把上面的 createDataSource() 方法实现替换如下:



重新对我们改过的代码作相同的测试,我们发现每次 conn.close() 之后,原来的连接状态仍然是 ESTABLISHED,下一次用 ds.getConnection() 取到的仍然是原来的连接,这样就达到了连接池化的目的。还有,一个实际生产环境用的连接池都会根据实际设置连接的最小及最大数量以及清除策略,是我们看到 OracleConnectionPoolDataSource 没有相应的设置项,这也没问题,还得靠 OracleConnectionCacheImpl 来设置 minLimit 和 maxLimit 属性。这里我们不显式的使用 OracleConnectionPoolDataSource,并且加上连接的最小最大连接量的设定,后的创建连接池的方法实现如下:


实际上 OracleConnectionCacheImpl 的 ConnectionPoolDataSource 还是 OracleConnectionPoolDataSource。浏览 OracleConnectionCacheImpl 的方法你可以加上更多的属性控制。如果有需要特别是在容器中应用,你可以把创建的 DataSource 绑定到上下文中,方便应用随时引用。

后记,我们看到 Oracle 的驱动包都是 1M 多,还是有些内涵的,只是鲜见有人用它自带的连接池实现,一般是考虑通用性,就说其实数据库的移植性绝大多时候只是个漂亮的晃子,想想你做的哪个系统在两种类型数据库上有部署过。Oracle 自带我想应有它的优势,毕竟人家最了解自己了。

刚开始我用 OracleConnectionPoolDataSource 一时改变不了用 BasicDataSource 的惯性思维,总在想:如何设置数据库的驱动类啊?其实根本用不着,只缘它身在驱动包中。

还有一种不使用 OracleConnectionCacheImpl 也能用上连接池,那就是每次取连接不从 DataSource 中取,而是从一个 PooledConnection 实例中取,在第一段代码中改 main() 方法取连接的代码为如下:



不过,这种用户确实让人觉得有些别扭,本人不赞同这么使用,对于使用者来说规约不明。

另外,在 WAS 中配置 Oracle 连接池时,WAS 还会用到一个数据源帮助程序类名 com.ibm.websphere.rsadapter.OracleDataStoreHelper,这是在 $WAS_HOME/lib/rsaexternal.jar 包中的,尚不清楚有何用。

此文的目的是为 WAS 作自定义安全认证用户注册表作铺垫,意图是 WAS 控制台及上的应用以配置方式通过数据库作 Form/Basic 认证,需要写一个自定义的 JdbcRegistry 实现 UserRegistry 接口,希望通过以上方式配置数据库连接池获得连接。

参考:1. 连接池是否有用? 
      2. 简单的数据库连接池(Oracle) 
      3. Oracle连接池的实现 
      4.
用Oracle自带的连接缓冲类的一个例子 
      5. ConnectionPoolDataSource这个接口是干什么用的 


[版权声明]
本站内文章,如未标注 [转载],均系原创或翻译之作,本人 Unmi 保留一切权利。本站原创及译作未经本人许可,不得用于商业用途及传统媒体。网络媒体可随意转载,或以此为基础进行演译,但务必以链接形式注明原始出处和作者信息,否则属于侵权行为。另对本站转载他处文章,俱有说明,如有侵权请联系本人,本人将会在第一时间删除侵权文章。及此说明,重之之重。
posted on 2008-01-16 14:47 隔叶黄莺 阅读(1051) 评论(2)  编辑  收藏

Feedback

# re: 为何不直接使用 Oracle 提供的连接池实现 2008-01-16 15:31 Paul Lin
好文章,分析得很详细。不过我有一个问题想和博主探讨一下。我也是采用Oracle自带的连接池实现。但在测试时发现setUrl这个方法会抛出异常。不知道为什么,后来改成这样

/**
     * Sets the connection data source.
     
*/

    
private void setConnectionDataSource() {
        
try 
{
            dbSource 
= new
 OracleConnectionPoolDataSource();

            
//
 Notice: Do not use setURL method to set url, never ever!!! use
            
//
 below methods instead
            
// -----------Paul configuration-----------

             dbSource.setURL(db_url);
             dbSource.setDatabaseName(
"paullin"
);
             dbSource.setServerName(
"192.168.0.169"
);
             dbSource.setPortNumber(
1521
);
             dbSource.setDriverType(
"thin"
);
             dbSource.setUser(db_user);
             dbSource.setPassword(db_pwd);
            }
 catch (SQLException sqle) {
            logger.error(sqle.getMessage(), sqle);
            sqle.printStackTrace();
        }

    }


不知博主是否知道是什么原因?
  回复  更多评论
  

# re: 为何不直接使用 Oracle 提供的连接池实现 2008-01-16 15:37 隔叶黄莺
@Paul Lin
我没碰到过,因为在WAS里有配置连接池属性时都是只配置一个URL,其他就不用配置了,从来没出现过问题,想问一下,楼上的是报了什么异常。  回复  更多评论
  




标题  
姓名  
主页
验证码 *  
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-01-16 14:50 编辑过