Frage

Ich habe eine seltsame Situation mit einer kleinen Anwendung in Java mit einem JDBC-OBDC. Ich inspiziere eine Datenbank mit der Databasemetadata -Klasse. Wenn ich das Programm ausführe, funktioniert alles ohne einProblem. Aber wenn ich debuggen möchte, um die Werte innerhalb des Resulsets zu sehen, das die Databasemetadata enthält, wird ein Java.sql.sqlexception nur geworfen, wenn ich innerhalb der Zeit einen Haltepunkt stelle. Hier ist mein 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();

Warum kann ich meinen Haltepunkt nicht in diesen Codeabschnitt einfügen?

Dies ist die 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 meinem Code bezieht sich auf

tableNamesAsOne = tableNamesAsOne + answer.getString("TABLE_NAME") + " ";

Vielen Dank.

War es hilfreich?

Lösung

Ich habe SQL Server installiert, um Ihr Problem zu reproduzieren und zu überprüfen.

Kurze Erklärung

Sie müssen die Werte lesen NUR EINMAL und in der BESTELLEN Sie erscheinen in der Auswahl. JDBCODBC saugt. Beim Debuggen lesen Sie sie mehrmals.

Lange Erklärung

Was Sie tun, ist Überprüfung eines staatlichen Objekts im Debugger, was zu dynamischen Ergebnissen führt.

In diesem Fall ist es das sun.jdbc.odbc.JdbcOdbcResultSet und den Ausdruck ausführen resultSet.getString(...) mehrmals. Das erste Mal funktioniert es (falls Ihr Haltepunkt den Thread ausnutzt, bevor das Ergebnis gefragt wird). Wenn Sie dann (oder Ihr Debugger) zweiten Mal den Wert des Ausdrucks erneut prüfen, die getString() Methode heißt wieder und diese Methode ändert den internen Zustand der ResultSet Objekt.

Obwohl der Name der Methode darauf hindeutet, dass es sich um einen einfachen Getter handelt, ist dies nicht der Fall. Es tut mehr als das. Es kann tatsächlich die Daten aus der Datenbank abrufen, ihre internen Positionszähler usw. ändern. Sie können die Getter -Methoden nicht mehrmals ausführen.

Der ODBC -Treiber ist eine sehr schlechte Sache und von geringer Qualität. Erwarten Sie seltsames Verhalten und andere Drachen. Sie können einige Debug -Informationen erhalten, indem Sie die JDBCODBC -Verfolgung aktivieren. Das geschieht durch Einstellen a LogWriter Auf dem DriverManager, bevor der JDBCODBC-BRIDGE aktiviert ist:

java.sql.DriverManager.setLogWriter(new PrintWriter(System.out));

Anschließend erhalten Sie die ausführliche Debugging-Ausgabe des JDBCODBC-Fahrers wie folgt. Es kann Ihnen helfen, das Problem zu debuggen, das Sie haben. Stellen Sie beim Debuggen einfach sicher, dass die Daten, die von den Ergebnisobjekten in lokalen Objekten abgerufen wurden, gespeichert werden, damit Sie sie mehrmals im Debugger überprüfen können.

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 und dies war die reproduzierte Ausnahme, einschließlich Zeilennummern des Sonnencodes für JDK 1.6.0_22. Wie Sie in der ersten Zeile sehen können, wird dies auf der Konsole ausgedruckt, wenn ich das inspizierte getString() Methode.

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)

Andere Tipps

Ja, der Debugger läuft in einem anderen Thread als die Metadaten, die er erhalten hat con.getMetaData();... Also, wissen Sie, es ist eine andere Transaktion mit einer anderen Metadaten.

Nun, ok, das wäre meine erste Vermutung. Ich habe den OBDC -Treiberquellcode nicht untersucht, um dies zu bestätigen.


EDIT: Danke für Mhaller ausgezeichnete Bemerkung und einen 2. Look/Vermutung: Sie nennen wesnull () vorzeitig, es hat eine Bedeutung, nachdem einige Einsätze des Ergebnisses erhalten haben. Kopie aus 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>.

Puh, ich saugt heute Nacht!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top