Java 在一个类中加载的Oracle JDBC驱动程序在同一个包中的另一个类中不可访问

Java 在一个类中加载的Oracle JDBC驱动程序在同一个包中的另一个类中不可访问,java,jdbc,oracle12c,wlst,classloading,Java,Jdbc,Oracle12c,Wlst,Classloading,我正在开发一个EAR应用程序(部署在WLS 12c上),该应用程序具有为Oracle配置和测试jdbc连接的功能。因此,在我的jsp页面中,用户选择驱动程序oracle.jdbc.OracleDriver,输入connectionurl、用户名和密码,然后单击testConnection。执行此操作时,应用程序将返回一个错误,说明java.sql.SQLException:找不到适用于 jdbc:oracle:thin:@XXX xx:1525/YYYY public static boolea

我正在开发一个EAR应用程序(部署在WLS 12c上),该应用程序具有为Oracle配置和测试jdbc连接的功能。因此,在我的jsp页面中,用户选择驱动程序oracle.jdbc.OracleDriver,输入connectionurl、用户名和密码,然后单击testConnection。执行此操作时,应用程序将返回一个错误,说明java.sql.SQLException:找不到适用于
jdbc:oracle:thin:@XXX xx:1525/YYYY

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;
}
简要介绍本应用程序中使用的体系结构:

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;
}
在应用程序启动时,我们引用一个具有所有JDBC默认值的xml,并尝试加载该xml中存在的所有受支持的JDBC驱动程序。oracle.jdbc.OracleDriver也是其中之一。这个注册是通过一个util类jdbcuti.java完成的,它有两个静态方法:registerdrive(String driverName)和isdriverregisted(String 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;
}
因此,第一次调用jdbcuti.registerDriver(“oracle.jdbc.OracleDriver”)时,isDriverRegistered返回false,在registerDriver中,我们调用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;
}
isDriverRegistered中的逻辑通过调用DriverManager.getDrivers获取向DriverManager注册的所有驱动程序的枚举,并检查传递给它的driverName字符串是否等于driver.getClass.getName

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;
}
在第一次调用OracleDriver的JDBCUtil后,对OracleDriver的registerDriver的任何后续调用都应跳过class.forName,因为isDriverRegistered应返回true。但在添加logs语句并进行调试时,我注意到每次为OracleDriver调用registerDriver->isDriverRegistered时,它总是返回false。通过调用DriverManager getDrivers获得的枚举从未包含OracleDriver

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中,我们调用jdbcuti.registerDriver(“oracle.jdbc.OracleDriver”),正如预期的那样,在registerDriver函数exceute class.forName(“oracle.jdbc.OracleDriver”)中调用jdbcuti.registerDriver,因为isdriverregisted返回false。在JDBCDS.java中,在调用registerDriver之后,我们通过传递url、usename和密码来调用DriverManager.getConnection。此调用正在抛出SQLException,表示NoSuitableDriverFound

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中调用Class.forName(“oracle.jdbc.OracleDriver”),然后调用DriverManager.getConnection,这次我成功地获得了连接

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;
}
在这个论坛上,我已经讨论了所有与NoSuitableDriverFound异常相关的问题,但是没有什么适合我的问题

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中的new oracle.jdbc.OracleDriver()来调用创建驱动程序的新实例,并查看它是否接受我的url。此外,这也排除了任何类路径问题。jar肯定在类路径中。我们的类路径包括以下内容:
com.oracle.db.jdbc7 dms.jar
以及weblogic.jar

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;
}
com.oracle.db.jdbc7 dms.jar
内部有一个指向ojdbc8dms.jar的链接,weblogic.jar内部通过MANIFEST.MF文件的Class Path属性包含ojdbc8.jar

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;
}
此外,此问题仅限于特定环境。在具有相同设置的其他环境中,一切正常,没有问题

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;
}
从JDBCUtil.java:

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;
}
用于注册驱动程序的静态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;
}
查看驱动程序是否已真正注册的静态方法:

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中用于执行测试连接的代码:

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;
}
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都在同一个包中

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;
}

有人能告诉我如何进一步解决这个问题吗?

从所有
Class.forName()
调用开始,您不需要所有这些。只需使用您的
jdbc:oracle…
URL,让
DriverManager
来解决问题。是的,这不是必需的,但为了向后兼容和驱动程序不兼容JDBC4的环境,我们保留了代码。此外,DriverManager文档确实指出,包含Class.forName不应导致任何问题。此外,在我的例子中,驱动程序似乎没有被服务加载器接收到?为什么?为什么不在应用程序中分发所需的JDBC驱动程序?JDBC4.0于2007年推出。不,我们使用的是weblogic附带的。目前weblogic已经将ojdbc8.jar作为其安装的一部分。我的意思是,万一某个特定客户出于某种原因想要使用它。此外,正如我已经提到的,理想情况下,它不应该引起任何问题。@user207421 OP似乎把他的JDBC驱动程序放在耳朵里,在这种情况下,用
类加载驱动程序。forName
仍然是必要的(尽管最好由应用程序服务器使用数据源管理器)。自动加载驱动程序只适用于初始类路径上的JDBC驱动程序,而不适用于上下文类路径中的驱动程序。从所有
class.forName()
调用开始,您不需要所有这些。只需使用您的
jdbc:oracle…
URL,让
DriverManager
来解决问题。是的,这不是必需的,但为了向后兼容和驱动程序不兼容JDBC4的环境,我们保留了代码。此外,DriverManager文档确实指出,包含Class.forName不应导致任何问题。此外,在我的例子中,驱动程序似乎没有被服务加载器接收到?为什么?为什么不在应用程序中分发所需的JDBC驱动程序?JDBC4.0于2007年推出。不,我们使用的是weblogic附带的。目前weblogic已经将ojdbc8.jar作为其安装的一部分。我只是想以防万一
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;
}