Pregunta

Tengo una situación extraña con una pequeña aplicación en Java usando un JDBC-OBDC. Estoy inspeccionando una base de datos utilizando la clase DataBASEMetAdata. Cuando ejecuto el programa, todo funciona sin ningún problema. Pero cuando quiero depurar para ver los valores dentro del resulto que contiene el DatabaseMetadata, Java.sql.sqlexception se arroja solo si pongo un punto de interrupción dentro del tiempo. Aquí está mi código:

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();

¿Por qué no puedo poner mi punto de ruptura en esta sección de código?

Este es el 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)

Línea snooper.java:56 En mi código se refiere a

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

Gracias.

¿Fue útil?

Solución

He instalado SQL Server para reproducir su problema y verificarlo.

Explicación corta

Debes leer los valores SÓLO UNA VEZ y en el ORDENAR Aparecen en la selección. JDBCODBC apesta. Mientras depurar, los estás leyendo varias veces.

Explicación larga

Lo que estas haciendo es Inspeccionar un objeto con estado en el depurador, que conduce a resultados dinámicos.

En este caso es el sun.jdbc.odbc.JdbcOdbcResultSet y ejecutando la expresión resultSet.getString(...) varias veces. La primera vez, funcionará (en caso de que su punto de interrupción suspenda el hilo antes de que se solicite el conjunto de resultados). Luego, la segunda vez que usted (o su depurador) inspecciona el valor de la expresión nuevamente, el getString() se llama método otra vez y este método cambia el estado interno del ResultSet objeto.

Aunque el nombre del método sugiere que es un Getter simple, no lo es. Hace más que eso. En realidad, puede recuperar los datos de la base de datos, cambiar sus contadores de posición internos, etc. No puede ejecutar los métodos Getter varias veces.

El controlador ODBC es algo muy malo y de baja calidad. Espere un comportamiento extraño y otros dragones. Puede obtener información de depuración habilitando el rastreo de JDBCODBC. Eso se hace configurando un LogWriter En el Drivermanager, antes de que se active el puente JDBCODBC:

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

Luego, obtendrá la salida de depuración detallada del JDBCODBC-Driver como lo siguiente. Puede ayudarlo a depurar el problema que tiene. Al depurar, solo asegúrese de almacenar los datos recuperados de los objetos de resultados de resultados en objetos locales, para que pueda inspeccionarlos varias veces en el depurador.

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

PD y esta fue la excepción reproducida, incluidos los números de línea del código Sun para JDK 1.6.0_22. Como puede ver en la primera línea, esto es lo que se imprime en la consola cuando inspeccioné el getString() método.

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)

Otros consejos

Sí, el depurador se ejecuta en un hilo diferente a los metadatos obtenidos por con.getMetaData();... Entonces, ya sabes, es una transacción diferente con metadatos diferentes.

Bueno, está bien, esa sería mi primera suposición. No he investigado el código fuente del controlador OBDC para confirmar.


EDITAR: Gracias por Mhaller Excelente Observación A hizo un segundo look/adivina: usted llama a Wasnull () prematuramente, tiene significado después de que algunos obtengan la operación del conjunto de resultados. Copiar de 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>.

¡Uf, chupa esta noche!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top