2011-01-25 7 views
2

JDBC-OBDC를 사용하여 Java에서 약간의 응용 프로그램으로 이상한 상황이 발생했습니다. DatabaseMetaData 클래스를 사용하여 데이터베이스를 검사하고 있습니다. 프로그램을 실행하면 모든 것이 문제없이 작동합니다. 그러나 DatabaseMetaData를 포함하고있는 Resulset 내부의 값을보기 위해 디버그를하고 싶을 때 java.sql.SQLException이 중단 점을 넣을 때만 throw됩니다. 내 코드는 다음과 같습니다.왜 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

게시글에 Exception을 추가했습니다. 감사. – jomaora

+0

질문이 명확하지 않습니다. 데이터베이스 (Oracle, MSSQL, MySQL) 란 무엇입니까? 어떤 Java IDE를 사용하고 있습니까? 브레이크 포인트를 설정하지 않고 IDE에서 실행하면 작동하지만 브레이크 포인트를 설정하면 예외가 발생한다고 말하는 것입니까? 예외를 즉시 얻는가? 아니면 두 번째로'answer.next()'를 통과 할 것인가? –

답변

3

문제점을 재현하고 확인하기 위해 SQL Server를 설치했습니다.

짧은 설명

당신은 값을 한 번만 그들이 SELECT에 나타나는 ORDER에서 을 읽어야합니다. JdbcOdbc는 빤다. 디버깅하는 동안 여러 번 읽는 중입니다.

긴 설명

당신이 동적 인 결과에 이르게 디버거에서 상태 기반 객체를 검사입니다 을 다하고 있습니다.

이 경우 sun.jdbc.odbc.JdbcOdbcResultSet이고 resultSet.getString(...)이라는 표현을 여러 번 실행합니다. 처음으로, resultSet이 요청되기 전에 중단 점이 스레드를 일시 중단하는 경우에 작동합니다. 그런 다음 두 번째로 다시 식의 값을 검사 할 때 getString() 메서드는 으로 다시이고이 메서드 ResultSet 개체의 내부 상태를 변경합니다.

메서드의 이름이 단순한 getter임을 나타내지 만, 그렇지 않습니다. 그것 이상입니다. 실제로 데이터베이스에서 데이터를 검색하고 내부 위치 카운터 등을 변경할 수 있습니다. getter 메소드를 여러 번 실행할 수 없습니다.

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. 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를 Access = DriverManager.getConnection ("jdbc : jstels : mdb : AirLine.mdb")이라는 드라이버로 변경했습니다. 예, debbuging 중에 문제없이 작동합니다. 실제로 우리는 선생님이 우리가 DB에 연결하고 metaData를 탐색하는 방법을 테스트하기를 원하기 때문에 JDBC ODBC를 사용하고 있습니다. 나는 그것이 빤다는 것을 안다. :피. 팁을 기록해 줘서 고마워. 매우 흥미로운. – jomaora

+0

드라이버는 결코 고쳐지지 않았으므로, 지금 말씀 드렸을 때, 나는 2000 년경에 MSSQL 용으로 사용해 보았습니다. 재앙이었습니다 (똑같은 문제가 있었고, 임의로 열에 액세스 할 수 없었고, 순서대로 있어야했습니다). 그래서 우리는 타사 소켓 기반의 소켓으로 전환했습니다. 위대한 발견! – bestsss

1

그래, 디버거는 con.getMetaData(); ...에 의해 얻은 메타 데이터와 다른 스레드에서 실행됩니다. 알다시피, 다른 메타 데이터를 사용하는 다른 트랜잭션입니다.

글쎄, 오케이, 내 첫 번째 추측이 될 것입니다. Obdc 드라이버 소스 코드를 확인하지 않았습니다.


편집 : mhaller 우수한 발언 만들를 제 2의 모양/추측에 대한 감사 : 당신은() 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가 아니라 스택 프레임이라고 말했습니다. 두 가지. 디버거는 중단 점이 있고 특정 스레드를 포함하는 동일한 프레임에서 표현식 (예 : 개체 검사 용)을 평가합니다. 예를 들어, 특정 스레드 또는 모든 스레드 만 중지하도록 Eclipse에 지시 할 수 있습니다. 디버거가 별도의 스레드를 사용하는 경우에는 불가능합니다. 정말로 일시 중지 된 스레드입니다. – mhaller

관련 문제