为什么我无法调试 DatabaseMetaData?
我有一个使用 JDBC-OBDC 的 Java 小应用程序,遇到了一个奇怪的情况。我正在使用 DatabaseMetaData 类检查数据库。当我执行该程序时,一切正常,没有任何问题。但是,当我想调试以查看包含 DatabaseMetaData 的结果集中的值时,仅当我在一段时间内放置断点时才会引发 java.sql.SQLException 。这是我的代码:
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") + " ";
谢谢。
I've a strange situation with a little application in Java using a JDBC-OBDC. I'm inspecting a Database using the DatabaseMetaData Class. When I execute the program, everything works without anyproblem. But when I want to debug to see the values inside the Resulset containing the DatabaseMetaData a java.sql.SQLException is thrown only if I put a breakpoint within the while. Here's my code:
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();
Why I cannot put my breakpoint in this section of code??
This is the 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)
Line Snooper.java:56 in my code refers to
tableNamesAsOne = tableNamesAsOne + answer.getString("TABLE_NAME") + " ";
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我已经安装了 SQL Server 来重现您的问题并验证它。
简短说明
您必须读取值ONLY ONCE,并且在 ORDER 中它们出现在 SELECT 中。 JdbcOdbc 很糟糕。在调试时,您会多次阅读它们。
长解释
您正在做的是检查调试器中的有状态对象,这会产生动态结果。
在本例中,它是
sun.jdbc.odbc.JdbcOdbcResultSet
并多次执行表达式resultSet.getString(...)
。第一次,它会起作用(如果你的断点在询问结果集之前挂起线程)。然后,当您(或您的调试器)再次检查表达式的值时,将再次调用getString()
方法,并且此方法会更改内部ResultSet
对象的状态。尽管该方法的名称表明它是一个简单的 getter,但事实并非如此。它的作用还不止于此。它实际上可能从数据库中检索数据,更改其内部位置计数器等。您不能多次执行 getter 方法。
ODBC 驱动程序是一个非常糟糕的东西,而且质量很低。期待奇怪的行为和其他龙。您可以通过启用 JdbcOdbc Tracing 来获取一些调试信息。这是通过在激活 JdbcOdbc-Bridge 之前在 DriverManager 上设置
LogWriter
来完成的:然后,您将获得 JdbcOdbc-Driver 的详细调试输出,如下所示。它可以帮助您调试遇到的问题。调试时,只需确保将从 ResultSet 对象检索到的数据存储在本地对象中,以便您可以在调试器中多次检查它们。
PS 这是重现的异常,包括 JDK 1.6.0_22 的 Sun 代码的行号。正如您在第一行中看到的,这是我检查
getString()
方法时在控制台上打印的内容。I have installed SQL Server to reproduce your problem and verify it.
Short explanation
You must read the values ONLY ONCE and in the ORDER they appear in the SELECT. JdbcOdbc sucks. While debugging, you're reading them multiple times.
Long explanation
What you are doing is inspecting a stateful object in the debugger, which leads to dynamic results.
In this case it's the
sun.jdbc.odbc.JdbcOdbcResultSet
and executing the expressionresultSet.getString(...)
multiple times. The first time, it will work (in case your breakpoint suspends the Thread before the resultSet is asked). Then, the second time you (or your debugger) inspects the value of the expression again, thegetString()
method is called again and this method changes the internal state of theResultSet
object.Although the method's name suggests it's a simple getter, it's not. It does more than that. It may actually retrieve the data from the database, change its internal position counters etc. You cannot execute the getter methods multiple times.
The ODBC Driver is a very bad thing and of low quality. Expect strange behavior and other dragons. You can get some debug information by enabling JdbcOdbc Tracing. That is done by setting a
LogWriter
on the DriverManager, before the JdbcOdbc-Bridge is activated:Then, you will get verbose debugging output of the JdbcOdbc-Driver like the following. It may help you to debug the problem you have. When debugging, just ensure to store the data retrieved from the ResultSet objects in local objects, so you can inspect them multiple times in the debugger.
P.S. And this was the reproduced exception, including line numbers of the Sun code for JDK 1.6.0_22. As you can see in the first line, this is what is printed out on the console when I inspected the
getString()
method.是的,调试器运行在与 con.getMetaData(); 获取的元数据不同的线程中...所以,您知道,这是具有不同元数据的不同事务。
好吧,这是我的第一个猜测。我还没有查看 Obdc 驱动程序源代码来确认。
编辑:
感谢 mhaller 的精彩评论,我进行了第二次查看/猜测:您过早地调用了 wasNull(),它在对 ResultSet 进行一些获取操作后才有意义。从 javadoc 复制
唷,我今晚真糟糕!
Yeah, the debugger runs in a different thread than the metadata obtained by
con.getMetaData();
... so, you know, it's a different transaction with a different metadata.Well, ok, that would be my 1st guess. I have not looked into Obdc driver source code to confirm.
Edit:
thanks for mhaller excellent remark a made a 2nd look/guess: you call wasNull() prematurely, it has meaning after some get operation of the ResultSet. Copy from javadoc
phew, me sucks tonight!