问题描述
我有一个使用 JDBC-OBDC 的 Java 小应用程序的奇怪情况.我正在使用 DatabaseMetaData 类检查数据库.当我执行程序时,一切正常.但是,当我想调试以查看包含 DatabaseMetaData 的 Resulset 中的值时,仅当我在其中放置断点时才会抛出 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") + " ";
谢谢.
推荐答案
我已经安装了 SQL Server 来重现您的问题并进行验证.
简短说明
您必须仅读取一次 并在 ORDER 中读取它们出现在 SELECT 中的值.JdbcOdbc 很烂.在调试时,您会多次阅读它们.
详细解释
您正在做的是在调试器中检查有状态的对象,这会导致动态结果.
在这种情况下,它是 sun.jdbc.odbc.JdbcOdbcResultSet 并多次执行表达式 resultSet.getString(...).第一次,它将起作用(如果您的断点在询问 resultSet 之前暂停线程).然后,第二次您(或您的调试器)再次检查表达式的值时,getString() 方法被调用 again 并且此方法改变了 ResultSet 对象的内部状态.
虽然该方法的名称表明它是一个简单的 getter,但事实并非如此.它的作用不止于此.它实际上可能从数据库中检索数据,更改其内部位置计数器等.您不能多次执行 getter 方法.
ODBC 驱动程序是一个非常糟糕且质量低下的东西.期待奇怪的行为和其他龙.您可以通过启用 JdbcOdbc Tracing 来获取一些调试信息.这是通过在 DriverManager 上设置一个 LogWriter 来完成的,在 JdbcOdbc-Bridge 被激活之前:
java.sql.DriverManager.setLogWriter(new PrintWriter(System.out));
然后,您将获得 JdbcOdbc-Driver 的详细调试输出,如下所示.它可以帮助您调试您遇到的问题.调试时,只需确保将从 ResultSet 对象中检索到的数据存储在本地对象中,这样您就可以在调试器中多次检查它们.
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
附:这是重现的异常,包括 JDK 1.6.0_22 的 Sun 代码的行号.正如您在第一行中看到的,这是我检查 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)