You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle JDBC连接异常:误加载MySQL驱动问题求助

解决多JDBC驱动共存时,Oracle连接被MySQL驱动错误拦截的问题

问题背景

你在尝试用sys用户(需SYSDBA身份)通过JDBC连接Oracle数据库时遇到了驱动冲突问题:

  • 项目同时引入了ojdbc6.jar(Oracle驱动)和mysql-connector-java-8.0.11.jar(MySQL驱动)
  • 执行Oracle连接代码时,MySQL驱动错误地尝试解析Oracle的连接URL,抛出了URL格式错误的异常
  • 移除MySQL驱动后,能得到预期的Oracle错误ORA-28009(提示连接SYS需用SYSDBA/SYSOPER身份)
  • 需要保留两个驱动的同时解决该问题

原始连接代码

private static Connection createConnectionOracle() { 
    Connection conn = null; 
    try { 
        Class.forName("oracle.jdbc.driver.OracleDriver"); 
        conn = DriverManager.getConnection(
            "jdbc:oracle:thin:@ (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.151)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orcl)))",
            "sys",
            "sys"
        ); 
    } catch (Exception e) { 
        e.printStackTrace(); 
    } 
    return conn; 
}

实际错误栈(MySQL驱动拦截导致)

java.sql.SQLNonTransientConnectionException: Cannot load connection class because of underlying exception: com.mysql.cj.exceptions.WrongArgumentException: Malformed database URL, failed to parse the main URL sections. 
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:108) 
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:95) 
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:87) 
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:61) 
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:71) 
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:79) 
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:131) 
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:231) 
at java.sql.DriverManager.getConnection(DriverManager.java:664) 
at java.sql.DriverManager.getConnection(DriverManager.java:247) 
at com.dataguise.discoverAgent.util.Test.createConnectionOracle(Test.java:399) 
at com.dataguise.discoverAgent.util.Test.main(Test.java:29) 
Caused by: com.mysql.cj.exceptions.UnableToConnectException: Cannot load connection class because of underlying exception: com.mysql.cj.exceptions.WrongArgumentException: Malformed database URL, failed to parse the main URL sections. 
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:59) 
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:103) 
... 5 more 
Caused by: com.mysql.cj.exceptions.WrongArgumentException: Malformed database URL, failed to parse the main URL sections. 
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:59) 
at com.mysql.cj.conf.ConnectionUrlParser.parseConnectionString(ConnectionUrlParser.java:139) 
at com.mysql.cj.conf.ConnectionUrlParser.<init>(ConnectionUrlParser.java:129) 
at com.mysql.cj.conf.ConnectionUrlParser.parseConnectionString(ConnectionUrlParser.java:118) 
at com.mysql.cj.conf.ConnectionUrl.getConnectionUrlInstance(ConnectionUrl.java:179) 
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:201) 
... 4 more

预期错误栈(移除MySQL驱动后)

java.sql.SQLException: ORA-28009: connection as SYS should be as SYSDBA or SYSOPER 
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445) 
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:389) 
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:382) 
at oracle.jdbc.driver.T4CTTIfun.processError(T4CTTIfun.java:600) 
at oracle.jdbc.driver.T4CTTIoauthenticate.processError(T4CTTIoauthenticate.java:445) 
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450) 
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192) 
at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:380) 
at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:760) 
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:401) 
at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:546) 
at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:236) 
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32) 
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:521) 
at java.sql.DriverManager.getConnection(DriverManager.java:664) 
at java.sql.DriverManager.getConnection(DriverManager.java:247) 
at com.dataguise.discoverAgent.util.Test.createConnectionOracle(Test.java:399) 
at com.dataguise.discoverAgent.util.Test.main(Test.java:29)

问题原因

DriverManager的工作机制是遍历所有注册的JDBC驱动,依次尝试用每个驱动去解析连接URL。MySQL的驱动在这里错误地认为自己可以处理Oracle的URL(没有正确判断URL前缀),导致它先于Oracle驱动抛出异常,中断了后续的驱动尝试流程。

解决方案

下面提供三种可靠的解决方法,按推荐程度排序:

1. 使用Oracle DataSource直接获取连接(推荐)

完全绕过DriverManager的驱动遍历逻辑,直接使用Oracle官方提供的OracleDataSource来创建连接,同时还能顺便解决ORA-28009的问题(指定SYSDBA身份):

private static Connection createConnectionOracle() {
    Connection conn = null;
    try {
        OracleDataSource ods = new OracleDataSource();
        // 设置Oracle连接URL
        ods.setURL("jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.151)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orcl)))");
        ods.setUser("sys");
        ods.setPassword("sys");
        // 指定SYSDBA身份,解决ORA-28009错误
        ods.setInternalLogon("sysdba");
        conn = ods.getConnection();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return conn;
}

2. 直接实例化Oracle驱动并调用connect方法

不依赖DriverManager的自动选择,手动使用Oracle驱动处理连接请求:

private static Connection createConnectionOracle() {
    Connection conn = null;
    try {
        // 直接创建Oracle驱动实例
        oracle.jdbc.driver.OracleDriver oracleDriver = new oracle.jdbc.driver.OracleDriver();
        Properties connectionProps = new Properties();
        connectionProps.setProperty("user", "sys");
        connectionProps.setProperty("password", "sys");
        // 添加SYSDBA身份属性
        connectionProps.setProperty("internal_logon", "sysdba");
        
        String oracleUrl = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.151)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orcl)))";
        conn = oracleDriver.connect(oracleUrl, connectionProps);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return conn;
}

3. 调整驱动注册顺序(可选,可靠性稍低)

JDBC4.0+会自动加载META-INF/services/java.sql.Driver中的驱动类。可以通过以下方式让Oracle驱动优先注册:

  • Maven依赖调整:在pom.xml中将Oracle的依赖放在MySQL依赖之前,类加载器会优先加载靠前的驱动
  • 手动注册驱动:在应用启动时先注册Oracle驱动,再注册MySQL驱动:
static {
    try {
        // 先注册Oracle驱动
        Class.forName("oracle.jdbc.driver.OracleDriver");
        // 再注册MySQL驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

注意:这种方法可能受类加载器策略影响,不如前两种方法稳定。


内容的提问来源于stack exchange,提问作者Ajay Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:02:02