我正在开发一个 EAR 应用程序(部署在 WLS 12c 上),它具有为 Oracle 配置和测试 jdbc 连接的功能。因此,在我的 jsp 页面中,用户选择驱动程序为 oracle.jdbc.OracleDriver,输入连接 URL、用户名和密码,然后单击 testConnection。在执行此操作时,应用程序会返回一个错误,说明 java.sql.SQLException:找不到合适的驱动程序
jdbc:oracle:thin:@XXX-xx:1525/YYYY
简要介绍此应用程序中使用的架构:
在应用程序启动时,我们指的是具有所有 JDBC 默认值的 xml,并尝试加载该 xml 中存在的所有受支持的 jdbc 驱动程序。而 oracle.jdbc.OracleDriver 也是其中之一。这种注册是通过一个实用类 JDBCUtil.java 完成的,它有 2 个静态方法:registerDriver(String driverName) 和 isDriverRegistered(String driverName)。
因此,第一次调用 JDBCUtil.registerDriver("oracle.jdbc.OracleDriver") 时,isDriverRegistered 返回 false,在 registerDriver 中,我们调用 class.forName(driverName) 来加载驱动程序。
isDriverRegistered 中的逻辑通过调用 DriverManager.getDrivers 获取向 DriverManager 注册的所有驱动程序的枚举,并检查传递给它的 driverName 字符串是否等于 driver.getClass.getName。
在第一次调用 OracleDriver 的 JDBCUtil 之后,对 OracleDriver 的 registerDriver 的任何后续调用都应跳过 class.forName,因为 isDriverRegistered 应返回 true。但是在添加日志语句和调试时,我注意到每次为 OracleDriver 调用 registerDriver->isDriverRegistered 时,它总是返回 false。调用 DriverManager getDrivers 得到的枚举,从不包含 OracleDriver。
其次,在另一个类 JDBCDS.java 中,我们调用 JDBCUtil.registerDriver("oracle.jdbc.OracleDriver") 并且正如预期的那样,在 registerDriver 函数中执行 Class.forName("oracle.jdbc.OracleDriver") 因为 isDriverRegistered 返回 false 。在 JDBCDS.java 中,在调用 registerDriver 之后,我们通过传入 url、用户名和密码来调用 DriverManager.getConnection。这个调用抛出 SQLException 说 NoSuitableDriverFound。
因此,作为另一个调试测试,我在 JDBCDS.java 中调用了 Class.forName("oracle.jdbc.OracleDriver") ,然后调用了 DriverManager.getConnection ,这一次我能够成功建立连接。
我已经在这个论坛上解决了所有与 NoSuitableDriverFound 异常相关的问题,但没有什么适合我的问题。
我试图通过在 JDBCDS.java 中调用 new oracle.jdbc.OracleDriver() 来调用创建驱动程序的新实例,并查看它是否接受我的 url 并且确实如此。此外,这也排除了任何类路径问题。jar 肯定在类路径中。我们的类路径包括以下内容:
com.oracle.db.jdbc7-dms.jar
以及 weblogic.jar
com.oracle.db.jdbc7-dms.jar
在这两种情况下,内部都有指向 ojdbc8dms.jar 的链接,而 weblogic.jar 内部通过其 MANIFEST.MF 文件的 Class-Path 属性包含了 ojdbc8.jar。
此外,此问题仅适用于特定环境。在具有相同设置的其他环境中,一切正常,没有问题。
从 JDBCUtil.java :
用于注册驱动程序的静态 Util 方法:
public static void registerDriver(String driverName)
{
// Calls isDriverRegistered,isDriverRegistered returns false, then call Class.forName(driverName)
}
查看驱动程序是否已注册的静态方法:
public static boolean isDriverRegistered(String driverName)
{
//call DriverManager.getDrivers to get all the registered drivers
if(driver.getClass().getName().equals(driverName))
{
return true;
}
return false;
}
JDBCDS.java 中用于执行测试连接的代码:
try {
JDBCUtil.registerDriver(driver);
DriverManager.setLoginTimeout(300);
conn = DriverManager.getConnection(url, username, password); //This code throws No Suitable Driver Found Exception
} catch (SQLException e) {
// tried the below as a test
try
{
Class.forName(driver);
}
catch(Exception ex)
{
Logger.log("Could not load the driver with the current classloader", 4);
throw e;
}
conn = DriverManager.getConnection(url, username, password);//At this step the connection is successfully obtained
}
JDBCUtil.java 和 JDBCDS.java 都在同一个包中。
谁能指出我可以做些什么来解决这个问题?