在 Oracle JDBC 连接上获取 MySQL 错误堆栈跟踪

Getting MySQL error stack trace on Oracle JDBC Connection

我在使用连接字符串建立 Oracle JDBC 连接时遇到了非常奇怪的错误。我将用户名设为 "sys"(应该是 sys 作为 sysdba),理想情况下,它应该来自 ojdbc6.jar 但在我的例子中,它来自 mysql-connector-java-8.0.11.jar 这也包含在我的项目中。请帮忙,因为我必须将这两个罐子保存在我的项目中。

当我删除 mysql-connector-java-8.0.11.jar 时,出现下面提到的预期 oracle 错误。

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

实际结果:

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

预期结果:

ava.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)

此错误发生在 MySQL Connector/J 8 版本 8.0.11 或更早版本(以及从未发布的 MySQL Connector/J 6 版本)。您需要升级到 8.0.12 或更高版本(当前最新版本为 8.0.17,请参阅 https://dev.mysql.com/downloads/connector/j/)。

来自Connector/J 8.0.12 release notes

When an application tried to connect to a non-MySQL database through some JDBC driver and Connector/J happened to be on the class path also, Connector/J threw a SQLNonTransientConnectionException, which prevented the application from connecting to its database. With this fix, Connector/J returns null whenever a connection string does not start with jdbc:mysql: or mysqlx:, so connections to non-MySQL databases are not blocked. (Bug #26724154, Bug #87600)

另见 https://bugs.mysql.com/bug.php?id=87600

作为背景,通常,JDBC 不支持特定 URL 的驱动程序(例如基于 jdbc: 之后的子协议),应该 return null,并且仅当 URL 用于驱动程序时才应抛出异常,但 URL 或创建连接存在问题。

然而,即使在 MySQL Connector/J 驱动程序中存在这个错误,您仍然可以连接到 Oracle 数据库,因为 DriverManager 将尝试每个驱动程序,直到它是能够打开一个连接。如果没有驱动程序能够连接,它将抛出任何驱动程序抛出的 first 异常,或者 - 如果所有驱动程序 returned null - 它会抛出一个"No suitable driver found" 异常。

在这种情况下,看起来 MySQL 是在 Oracle 驱动程序之前尝试过的驱动程序,正如您预期的那样,您的 Oracle 连接也会失败,它恰好抛出了 MySQL 异常,因为那是第一个例外。

长话短说,更新您的 MySQL Connector/J。