为什么我不能调试数据库emetadata?
-
24-10-2019 - |
题
我使用JDBC-OBDC在Java中进行了少量应用程序,我的情况很奇怪。我正在使用DataBaseMetadata类检查数据库。当我执行程序时,一切都在没有任何问题的情况下工作。但是,当我想调试时,只有在我在段落内放置断点时,才会抛出包含数据库的resulset中的值。这是我的代码:
DatabaseMetaData patrol = con.getMetaData();
ResultSet answer = patrol.getTables(null, null, null, null);
while(answer.next()) {
if (answer.wasNull() == false) {
tableNamesAsOne = tableNamesAsOne + answer.getString("TABLE_NAME") + " ";
}
}
answer.close();
为什么我不能将断点放在代码的这一部分中?
这是PrintStackTrace。
Exception in thread "main" java.sql.SQLException: No data found
at sun.jdbc.odbc.JdbcOdbc.standardError(Unknown Source)
at sun.jdbc.odbc.JdbcOdbc.SQLGetDataString(Unknown Source)
at sun.jdbc.odbc.JdbcOdbcResultSet.getDataString(Unknown Source)
at sun.jdbc.odbc.JdbcOdbcResultSet.getString(Unknown Source)
at sun.jdbc.odbc.JdbcOdbcResultSet.getString(Unknown Source)
at Snooper.inspect(Snooper.java:56)
at Snooper.<init>(Snooper.java:26)
at Snooper.createAndShowGUI(Snooper.java:112)
at Snooper.main(Snooper.java:125)
snooper.java:56在我的代码中是指
tableNamesAsOne = tableNamesAsOne + answer.getString("TABLE_NAME") + " ";
谢谢。
解决方案
我已经安装了SQL Server来重现您的问题并验证它。
简短的解释
您必须阅读值 只有一次 在 命令 它们出现在选择中。 JDBCODBC很烂。在调试时,您正在多次阅读它们。
长期解释
你在做什么 检查调试器中的状态物体, ,导致动态结果。
在这种情况下,是 sun.jdbc.odbc.JdbcOdbcResultSet
并执行表达式 resultSet.getString(...)
多次。第一次,它将起作用(如果您的断点在询问结果集之前暂停线程)。然后,您(或您的调试器)第二次再次检查表达式的值 getString()
方法被调用 再次 和这个方法 改变了内部状态 ResultSet
目的.
尽管该方法的名称表明这是一个简单的getter,但事实并非如此。它做得不仅如此。它实际上可以从数据库中检索数据,更改其内部位置计数器等。您不能多次执行Getter方法。
ODBC驱动程序是一件非常糟糕的事情,而且质量低。期待奇怪的行为和其他龙。您可以通过启用JDBCODBC跟踪来获取一些调试信息。这是通过设置 LogWriter
在Drivermanager上,在激活JDBCODBC-Bridge之前:
java.sql.DriverManager.setLogWriter(new PrintWriter(System.out));
然后,您将获得JDBCODBC-DRIVER的详细调试输出,如以下内容。它可能会帮助您调试您遇到的问题。调试时,只需确保将从结果集对象检索到的数据存储在本地对象中,以便您可以在调试器中多次检查它们。
DriverManager.getConnection("jdbc:odbc:testdbodbc")
JdbcOdbcDriver class loaded
registerDriver: driver[className=sun.jdbc.odbc.JdbcOdbcDriver,sun.jdbc.odbc.JdbcOdbcDriver@7b479feb]
DriverManager.initialize: jdbc.drivers = null
JDBC DriverManager initialized
trying driver[className=sun.jdbc.odbc.JdbcOdbcDriver,sun.jdbc.odbc.JdbcOdbcDriver@7b479feb]
*Driver.connect (jdbc:odbc:testdbodbc)
JDBC to ODBC Bridge: Checking security
No SecurityManager present, assuming trusted application/applet
JDBC to ODBC Bridge 2.0001
Current Date/Time: Wed Jan 26 00:31:27 CET 2011
Loading JdbcOdbc library
Allocating Environment handle (SQLAllocEnv)
hEnv=115724512
Allocating Connection handle (SQLAllocConnect)
hDbc=116219184
Connecting (SQLDriverConnect), hDbc=116219184, szConnStrIn=DSN=testdbodbc
RETCODE = 1
WARNING - Generating SQLWarning...
SQLWarning: reason([Microsoft][ODBC SQL Server Driver][SQL Server]Changed database context to 'master'.) SQLState(01000) vendor code(5701)
SQLWarning: reason([Microsoft][ODBC SQL Server Driver][SQL Server]Changed language setting to us_english.) SQLState(01000) vendor code(5703)
*Connection.getMetaData
*DatabaseMetaData.getDriverName
Get connection info string (SQLGetInfo), hDbc=116219184, fInfoType=6, len=300
SQLSRV32.DLL
*DatabaseMetaData.getDriverVersion
Get connection info string (SQLGetInfo), hDbc=116219184, fInfoType=7, len=300
06.01.7600
*DatabaseMetaData.getDriverName
Get connection info string (SQLGetInfo), hDbc=116219184, fInfoType=6, len=300
SQLSRV32.DLL
Driver name: JDBC-ODBC Bridge (SQLSRV32.DLL)
*DatabaseMetaData.getDriverVersion
PS这是复制的例外,包括JDK 1.6.0_22的太阳代码的线号。正如您在第一行中看到的那样,这是我检查时在控制台上打印的内容 getString()
方法。
Get string data (SQLGetData), hStmt=108067024, column=3, maxLen=257
RETCODE = 100
ERROR - No data found
java.sql.SQLException: No data found
at sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7138)
at sun.jdbc.odbc.JdbcOdbc.SQLGetDataString(JdbcOdbc.java:3907)
at sun.jdbc.odbc.JdbcOdbcResultSet.getDataString(JdbcOdbcResultSet.java:5698)
at sun.jdbc.odbc.JdbcOdbcResultSet.getString(JdbcOdbcResultSet.java:354)
at sun.jdbc.odbc.JdbcOdbcResultSet.getString(JdbcOdbcResultSet.java:411)
at sandbox.DatabaseMetadataTest.testDBMetadata(DatabaseMetadataTest.java:27)
其他提示
是的,调试器以与获得的元数据不同 con.getMetaData();
...所以,您知道,这是与不同的元数据的另一回事。
好吧,好吧,那将是我的第一个猜测。我尚未研究OBDC驱动程序源代码以确认。
编辑:感谢Mhaller的出色言论,A Made Ad Made Away/Guess:您过早地调用wasnull(),这意味着在对结果集进行某些操作后。从Javadoc复制
* Note that you must first call one of the getter methods * on a column to try to read its value and then call * the method <code>wasNull</code> to see if the value read was * SQL <code>NULL</code>.
PH,我今晚很烂!