我使用JDBC-OBDC在Java中使用一个小应用程序时出现了奇怪的情况。我正在使用DatabaseMetaData类检查数据库。当我执行程序时,一切都没有任何问题。但是当我想调试以查看包含DatabaseMetaData的Resulset中的值时,只有在我在while中放置断点时才会抛出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)
我的代码中的Line Snooper.java:56指的是
tableNamesAsOne = tableNamesAsOne + answer.getString("TABLE_NAME") + " ";
感谢。
答案 0 :(得分:3)
我已经安装了SQL Server来重现您的问题并进行验证。
您必须阅读SELECT中出现的值 ONLY ONCE 和 ORDER 。 JdbcOdbc糟透了。在调试时,你会多次阅读它们。
您正在做的是检查调试器中的有状态对象,这会产生动态结果。
在这种情况下,它是sun.jdbc.odbc.JdbcOdbcResultSet
并多次执行表达式resultSet.getString(...)
。第一次,它将工作(如果您的断点在询问resultSet之前挂起Thread)。然后,第二次(或您的调试器)再次检查表达式的值时,getString()
方法再次被称为 ,此方法会更改{{}的内部状态1}}对象。
虽然该方法的名称表明它是一个简单的吸气剂,但事实并非如此。它不止于此。它实际上可能从数据库中检索数据,更改其内部位置计数器等。您无法多次执行getter方法。
ODBC驱动程序非常糟糕且质量低劣。期待奇怪的行为和其他龙。您可以通过启用JdbcOdbc跟踪来获取一些调试信息。这是通过在激活JdbcOdbc-Bridge之前在DriverManager上设置ResultSet
来完成的:
LogWriter
然后,您将获得如下所示的JdbcOdbc-Driver的详细调试输出。它可以帮助您调试您遇到的问题。调试时,只需确保将从ResultSet对象中检索到的数据存储在本地对象中,这样就可以在调试器中多次检查它们。
java.sql.DriverManager.setLogWriter(new PrintWriter(System.out));
P.S。这是重现的异常,包括JDK 1.6.0_22的Sun代码的行号。正如您在第一行中看到的那样,这是我在检查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
方法时打印在控制台上的内容。
getString()
答案 1 :(得分:1)
是的,调试器在与con.getMetaData();
获得的元数据不同的线程中运行...所以,你知道,这是一个具有不同元数据的不同事务。
编辑: 感谢mhaller优秀的评论a第二次看/猜测:你过早地调用了wasNull(),它在一些getSet操作后有意义。从javadoc
复制p pw,我今晚很糟糕!* 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>.