为什么我无法调试DatabaseMetaData?

时间:2011-01-25 16:04:29

标签: java debugging sqlexception database-metadata

我使用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") + " ";

感谢。

2 个答案:

答案 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();获得的元数据不同的线程中运行...所以,你知道,这是一个具有不同元数据的不同事务。

好吧,好吧,这将是我的第一次猜测。我没有查看Obdc驱动程序源代码来确认。


编辑: 感谢mhaller优秀的评论a第二次看/猜测:你过早地调用了wasNull(),它在一些getSet操作后有意义。从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>.
p pw,我今晚很糟糕!