在 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。
我在使用连接字符串建立 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。