2011-01-25 9 views
2

私は、JDBC-OBDCを使用してJavaで小さなアプリケーションを使用すると奇妙な状況に陥りました。私はDatabaseMetaDataクラスを使用してデータベースを検査しています。プログラムを実行すると、すべての問題がなくなります。しかし、DatabaseMetaDataを含むResulset内の値を表示するためにデバッグしたいときは、中にブレークポイントを置いた場合にのみjava.sql.SQLExceptionがスローされます。私のコードは次のとおりです。なぜDatabaseMetaDataをデバッグできないのですか?

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) 

ラインSnooper.java:56は

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

感謝を指します。

+4

あなたはSQLExceptionを投稿できますか?あなたは接続が長時間待つことになるので、たぶんそれは何らかのタイムアウトです... –

+0

私は投稿に例外を追加しました。ありがとう。 – jomaora

+0

あなたの質問は明確ではありません。データベース(Oracle、MSSQL、MySQL)とは何ですか?どのJava IDEを使用していますか?ブレークポイントが設定されていない状態でIDEで実行すると、動作しますが、ブレークポイントを設定すると例外が発生すると言っていますか?あなたは例外をすぐに取得するのですか?または、2回目に 'answer.next()'を渡しますか? –

答えて

3

問題を再現して確認するためにSQL Serverをインストールしました。

短い説明

あなたはONLY ONCE、彼らはSELECTに表示されORDERに値を読み取る必要があります。 JdbcOdbcは吸う。デバッグ中は、それらを複数回読み込んでいます。何をやっている

ロング説明

は、ダイナミックな結果につながるデバッガ、ステートフルオブジェクトを検査です。

この場合、sun.jdbc.odbc.JdbcOdbcResultSetであり、式resultSet.getString(...)を複数回実行しています。初めて(resultSetが要求される前にブレークポイントがスレッドを中断した場合に備えて)動作します。次に、再度(またはデバッガ)式の値を再度検査すると、getString()メソッドはとなり、このメソッドResultSetオブジェクトの内部状態を変更します。

メソッドの名前は単純なゲッターであることを示していますが、そうではありません。それ以上のことをします。実際には、データベースからデータを取得したり、内部位置カウンタなどを変更したりすることがあります。ゲッターメソッドを複数回実行することはできません。

ODBCドライバは非常に悪いことであり、低品質です。奇妙な行動や他のドラゴンを期待する。 JdbcOdbcトレースを使用可能にすると、デバッグ情報を取得できます。 JdbcOdbcブリッジが起動する前には、DriverManagerの上LogWriterを設定することによって行われます。

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

その後、あなたは次のようなJdbcOdbc-ドライバーの詳細なデバッグ出力を取得します。あなたが持っている問題をデバッグするのに役立ちます。デバッグ時には、ResultSetオブジェクトから取得したデータをローカル・オブジェクトに格納して、デバッガで複数回検査できるようにしてください。

DriverManager.getConnection("jdbc:odbc:testdbodbc") 
JdbcOdbcDriver class loaded 
registerDriver: driver[className=sun.jdbc.odbc.JdbcOdbcDriver,[email protected]] 
DriverManager.initialize: jdbc.drivers = null 
JDBC DriverManager initialized 
    trying driver[className=sun.jdbc.odbc.JdbcOdbcDriver,[email protected]] 
*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 

P.S.これは、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) 
+0

Ok ...私はあなたが何度もデータを呼び出すJDBC OBDCについて言います。ありがとうございました...私はJDBC OBDCを、Driver = AccessManager.getConnection( "jdbc:jstels:mdb:AirLine.mdb")と呼ばれるアクセス用のドライバで変更しました。はい、debbuging中に問題なく動作します。実際には、先生がDBに接続してmetaDataを探索するためにこの方法をテストしてほしいので、JDBC ODBCを使用しています。私はそれが吸うことを知っている。 :P。また、ログを見るためのヒントに感謝します。とても興味深い。 – jomaora

+0

ドライバは決して固定されていませんでしたので、今私が2000年ごろMSSQLで使用しようとしたことを思い出しましたが、それは災害でした(まったく同じ問題でした。私たちは第三者ソケットベースのものに切り替えました。素晴らしい発見! – bestsss

1

ええ、デバッガは、con.getMetaData();で取得されたメタデータとは異なるスレッドで実行されます。つまり、異なるメタデータを持つ別のトランザクションです。

まあ、それは私の最初の推測だろう。私は確認するためにObdcドライバのソースコードを調べていない。


編集:mhaller優れた発言なさ第二見た目/推測のための 感謝:あなたは()を呼び出してwasNull一部がResultSetの操作を取得した後に途中で、それが意味を持ちます。 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>. 

あーからコピーし、私は今夜を吸います!

+0

の可能性があります。同じスタックフレームを使用しているので、デバッガは同じスレッドで実行されます。 – mhaller

+0

スタックトレースがデバッガによって印刷されることを意味しますか? – bestsss

+0

いいえ、私はstacktraceではなく、スタックフレームを言った。 2つの異なるもの。デバッガは、ブレークポイントが存在し、特定のスレッドを含む同じフレーム内の式を評価する(例えば、オブジェクトを検査するために)。たとえば、特定のスレッドまたはすべてのスレッドのみを停止するようEclipseに指示できます。これは、デバッガが別のスレッドを使用する場合は不可能です。実際には中断されているスレッドです。 – mhaller

関連する問題