Databasemetadataをデバッグできないのはなぜですか?
-
24-10-2019 - |
質問
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をインストールして、問題を再現して確認しました。
簡単な説明
値を読む必要があります 1回だけ とで 注文 それらはselectに表示されます。 jdbcodbcは吸う。デバッグ中、あなたはそれらを複数回読んでいます。
長い説明
あなたがしていることはです デバッガーでステートフルなオブジェクトを検査します, 、動的な結果につながります。
この場合、それはです sun.jdbc.odbc.JdbcOdbcResultSet
式を実行します resultSet.getString(...)
複数回。初めては機能します(結果セットが求められる前にブレークポイントがスレッドを一時停止した場合)。それから、あなた(またはあなたのデバッガー)が式の価値を再び検査する2回目、 getString()
メソッドが呼び出されます また そして、この方法 の内部状態を変更します ResultSet
物体.
この方法の名前は、それがシンプルなゲッターであることを示唆していますが、そうではありません。それ以上のことをします。実際にデータベースからデータを取得し、内部位置カウンターなどを変更する場合があります。ゲッターメソッドを複数回実行することはできません。
ODBCドライバーは非常に悪いものであり、低品質です。奇妙な行動や他のドラゴンを期待してください。 JDBCODBCトレースを有効にすることで、いくつかのデバッグ情報を取得できます。それはaを設定することによって行われます LogWriter
DriverManagerでは、JDBCODBC-BRIDGEがアクティブ化される前の前に:
java.sql.DriverManager.setLogWriter(new PrintWriter(System.out));
次に、以下のようにJDBCODBC-DRIVERの冗長デバッグ出力を取得します。それはあなたが持っている問題をデバッグするのに役立つかもしれません。デバッグするときは、結果セットオブジェクトから取得したデータをローカルオブジェクトのオブジェクトから保存してください。デバッガーで複数回検査できるようにしてください。
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そして、これはJDK 1.6.0_22のサンコードの行番号を含む、再現された例外でした。あなたが最初の行で見ることができるように、これは私が検査したときにコンソールに印刷されるものです 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)
他のヒント
ええ、デバッガーは、によって得られたメタデータとは異なるスレッドで実行されます con.getMetaData();
...だから、ご存知のように、それは異なるメタデータを使用した別のトランザクションです。
まあ、OK、それは私の最初の推測でしょう。確認するOBDCドライバーソースコードを調べていません。
編集:Mhallerの優れた発言に感謝します。 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>.
うーん、私は今夜吸う!