日期:2014-05-16  浏览次数:20422 次

不同DataSource类对Oracle数据库url的识别

使用Spring辅助Hibernat操作Oracle数据库,驱动使用 classes12.jar ,先在配置文件applicationContext.xml中配置DataSource,初始使用内

置的DriverManagerDataSource作试验,连接数据库、CRUD记录均无错。这时配置文件中有关dataSource的配置信息如下:

??? <bean id="dataSource"
????????? class="org.springframework.jdbc.datasource.DriverManagerDataSource">
??????? <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
??????? <property name="url" value="jbdc:oracle:thin:@172.16.0.220:1521:enterinfo"/>
??????? <property name="username" value="enterinfo"/>
??????? <property name="password" value="enterinfo"/>
??? </bean>

在其它内容均不动的情况下,单纯将DriverManagerDataSource改为Apache DBCP的BasicDataSource, 报错:

Exception in thread "main" org.apache.commons.dbcp.SQLNestedException: Cannot create JDBC driver of class

'oracle.jdbc.driver.OracleDriver' for connect URL ':oracle:thin:@172.16.0.220:1521:enterinfo'
??? at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1150)
??? at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
??? at Test.main(Test.java:16)
Caused by: java.sql.SQLException: No suitable driver
??? at java.sql.DriverManager.getDriver(Unknown Source)
??? at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1143)
??? ... 2 more

没合适的驱动是因为驱动程序没有加载吗?不对,刚使用DriverManagerDataSource一点问题均没有。还是因为BasicDataSource类名写错,如

果是这样应该抛ClassNotFoundException,也不对。只有一种可能:URL写错。仔细检查,j,d,b,c,冒号 ...。果不其然,将 jdbc 写成 jbdc

。改正,一切又恢复正常。

真粗心啊!懊恼之余,想想:Spring真神奇,能自动纠正url的错误?能实例化Bean对象、装配对象间关系,管理对象生命周期,还能...? 不

可能!JDBC中DriverManager也好,Spring中DriverManagerDataSource也好以及DBCP的BasiceDataSource也好,无非是对Driver对象的进一步

包装,真正创建连接,识别判断URL正误的是java.sql.Driver接口的实现类,而该类是Oracle官网所下。以此作为指导方向,怀着打破砂锅问

到底的态度,向源码进发:

先打开DriverManagerDataSource的源码(Spring2.5.1版本),虽然Spring 2.5.1版本出来不久,但该类创建时间却较早:since 14.03.2003。找

到 getConnection()方法处,只有一行代码:

return getConnectionFromDriverManager();

再看 getConnectionFromDriverManager(),又只有一行,转而调用 getConnectionFromDriverManager(getUsername(), getPassword());而后

面这个方面也简单,将用户名称和密码封装成 Properties 对象,转而调用 getConnectionFromDriverManager(String url, Properties

props)。最后在该方法中找到建立连接最核心的代码:

return DriverManager.getConnection(url, props);

看到这,我们能理解,为什么说Spring的DriverManagerDataSource没有连接池化功能了。DriverManager.getConnection()无非转而调用

Driver.connect()方法,难道真的是Oracle的驱动问题?继续实验,写一个最简单的JDBC连接程序:

??????? String???? driverName="oracle.jdbc.driver.OracleDriver";
??????? String???? url="jbdc:oracle:thin:@172.16.0.220:1521:enterinfo";
??????? String???? username="enterinfo";
??????? String???? password="enterinfo";
??????? Connection conn=null;

??????? try{
??????????? Class.forName(driverName);
??????????? conn=DriverManager.getConnection(url,username,password);????????? ?
??????? } catch(Exception e) {
??????????? e.printStackTrace();
??????? } finally {
??????????? if(conn!=null) try {conn.close();}catch(Exception e){}
??????? }
??????? System.out.println(conn);

刻意将url第一个单词 jdbc 写成 jbdc, 能正确连接。写成 jaaa, 能正确连接,写成 aaaa, 能正确连接。去掉,能正确连接。实验结果表明

,这时Oracle驱动压根就未对第一个冒号前的内容进行验正。

至此,粗步得到结论:DriverManagerDataSource仅是对DriverManager的getConnection(url,username,password)进行了简单包装。

那Apache的DBCP中BasicDataSource呢?打开BasicDataSource,同样定位至getConnection()方法处。该方法也是一行:return

createDataSource().getConnection(); 继承定位至 createDataSource() 方法,这个方法就较复杂一点,结合之前的错误提示(at

org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1150)),将目光聚焦在该方法接下来几行:

1140??????? // Create a JDBC