## Recuperar Valores de una Hoja de Resultados

Ahora veremos como enviar la sentencia SELECT de la página anterior desde un programa escrito en Java y como obtener los resultados que hemos mostrado.

JDBC devuelve los resultados en un objeto ResultSet, por eso necesitamos declarar un ejemplar de la clase ResultSet para contener los resultados. El siguiente código presenta el objeto ResultSet: rs y le asigna el resultado de una consulta anterior:

    ResultSet rs = stmt.executeQuery("SELECT COF_NAME, PRICE FROM COFFEES");

#### Utilizar el Método next

La variable rs, que es un ejemplar de ResultSet, contiene las filas de cafés y sus precios mostrados en el juego de resultados de la página anterior. Para acceder a los nombres y los precios, iremos a la fila y recuperaremos los valores de acuerdo con sus tipos. El método next mueve algo llamado cursor a la siguiente fila y hace que esa fila (llamada fila actual) sea con la que podamos operar. Como el cursor inicialmente se posiciona justo encima de la primera fila de un objeto ResultSet, primero debemos llamar al método next para mover el cursor a la primera fila y convertirla en la fila actual. Sucesivas invocaciones del método next moverán el cursor de línea en línea de arriba a abajo. Observa que con el JDBC 2.0, cubierto en la siguiente sección, se puede mover el cursor hacia atrás, hacia posiciones específicas y a posiciones relativas a la fila actual además de mover el cursor hacia adelante.

#### Utilizar los métodos getXXX

Los métodos getXXX del tipo apropiado se utilizan para recuperar el valor de cada columna. Por ejemplo, la primera columna de cada fila de rs es COF_NAME, que almacena un valor del tipo VARCHAR de SQL. El método para recuperar un valor VARCHAR es getString. La segunda columna de cada fila almacena un valor del tipo FLOAT de SQL, y el método para recuperar valores de ese tipo es getFloat. El siguiente código accede a los valores almacenados en la fila actual de rs e imprime una línea con el nombre seguido por tres espacios y el precio. Cada vez que se llama al método next, la siguiente fila se convierte en la actual, y el bucle continúa hasta que no haya más filas en rs:

    String query = "SELECT COF_NAME, PRICE FROM COFFEES";
    ResultSet rs = stmt.executeQuery(query);
    		while (rs.next()) {
    		String s = rs.getString("COF_NAME");
    		Float n = rs.getFloat("PRICE");
    		System.out.println(s + "   " + n);
    }

La salida se parecerá a esto:

    Colombian   7.99
    French_Roast   8.99
    Espresso   9.99
    Colombian_Decaf   8.99
    French_Roast_Decaf   9.99

Veamos cómo funcionan los métodos getXXX examinando las dos sentencias getXXX de este código. Primero examinaremos getString.

    String s = rs.getString("COF_NAME");

El método getString es invocado sobre el objeto ResultSet: rs, por eso getString recuperará (obtendrá) el valor almacenado en la columna COF_NAME de la fila actual de rs. El valor recuperado por getString se ha convertido desde un VARCHAR de SQL a un String de Java y se ha asignado al objeto String s. Observa que utilizamos la variable s en la expresión println mostrada arriba, de esta forma: println(s + " " + n)

La situación es similar con el método getFloat excepto en que recupera el valor almacenado en la columna PRICE, que es un FLOAT de SQL, y lo convierte a un float de Java antes de asignarlo a la variable n.

JDBC ofrece dos formas para identificar la columna de la que un método getXXX obtiene un valor. Una forma es dar el nombre de la columna, como se ha hecho arriba. La segunda forma es dar el índice de la columna (el número de columna), con un 1 significando la primera columna, un 2 para la segunda, etc. Si utilizáramos el número de columna en vez del nombre de columna el código anterior se podría parecer a esto:

    String s = rs.getString(1);
    float n = rs.getFloat(2);

La primera línea de código obtiene el valor de la primera columna de la fila actual de rs (columna COF_NAME), convirtiéndolo a un objeto String de Java y asignándolo a s. La segunda línea de código obtiene el valor de la segunda columna de la fila actual de rs, lo convierte a un float de Java y lo asigna a n. Recuerda que el número de columna se refiere al número de columna en la hoja de resultados no en la tabla original.

En suma, JDBC permite utilizar tanto el nombre cómo el número de la columna como argumento a un método getXXX. Utilizar el número de columna es un poco más eficiente, y hay algunos casos donde es necesario utilizarlo.

JDBC permite muchas lateralidades para utilizar los métodos getXXX para obtener diferentes tipos de datos SQL. Por ejemplo, el método getInt puede ser utilizado para recuperar cualquier tipo numérico de caracteres. Los datos recuperados serán convertidos a un int; esto es, si el tipo SQL es VARCHAR, JDBC intentará convertirlo en un entero. Se recomienda utilizar el método getInt sólo para recuperar INTEGER de SQL, sin embargo, no puede utilizarse con los tipos BINARY, VARBINARY, LONGVARBINARY, DATE, TIME, o TIMESTAMP de SQL.

Métodos para Recuperar Tipos SQL muestra qué métodos pueden utilizarse legalmente para recuperar tipos SQL, y más importante, qué métodos están recomendados para recuperar los distintos tipos SQL. Observa que esta tabla utiliza el término "JDBC type" en lugar de "SQL type." Ambos términos se refieren a los tipos genéricos de SQL definidos en java.sql.Types, y ambos son intercambiables.

#### Utilizar el método getString

Aunque el metodo getString está recomendado para recuperar tipos CHAR y VARCHAR de SQL, es posible recuperar cualquier tipo básico SQL con él. (Sin embargo, no se pueden recuperar los nuevos tipos de datoas del SQL3. Explicaremos el SQL3 más adelante).

Obtener un valor con getString puede ser muy útil, pero tiene sus limitaciones. Por ejemplo, si se está utilizando para recuperar un tipo numérico, getString lo convertirá en un String de Java, y el valor tendrá que ser convertido de nuevo a número antes de poder operar con él.

#### Utilizar los métodos de ResultSet.getXXX para Recuperar tipos JDBC

| TINYINT | SMALLINT | INTEGER | BIGINT | REAL | FLOAT | DOUBLE | DECIMAL | NUMERIC | BIT | CHAR | VARCHAR | LONGVARCHAR | BINARY | VARBINARY | LONGVARBINARY | DATE | TIME | TIMESTAMP
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
#### getByte | X | x | x | x | x | x | x | x | x | x | x | x | x |  |  |  |  |  |
#### getShort | x | X | x | x | x | x | x | x | x | x | x | x | x |  |  |  |  |  |
#### getInt | x | x | X | x | x | x | x | x | x | x | x | x | x |  |  |  |  |  |
#### getLong | x | x | x | X | x | x | x | x | x | x | x | x | x |  |  |  |  |  |
#### getFloat | x | x | x | x | X | x | x | x | x | x | x | x | x |  |  |  |  |  |
#### getDouble | x | x | x | x | x | X | X | x | x | x | x | x | x |  |  |  |  |  |
#### getBigDecimal | x | x | x | x | x | x | x | X | X | x | x | x | x |  |  |  |  |  |
#### getBoolean | x | x | x | x | x | x | x | x | x | X | x | x | x |  |  |  |  |  |
#### getString | x | x | x | x | x | x | x | x | x | x | X | X | x | x | x | x | x | x | x
#### getBytes |  |  |  |  |  |  |  |  |  |  |  |  |  | X | X | x |  |  |
#### getDate |  |  |  |  |  |  |  |  |  |  | x | x | x |  |  |  | X |  | x
#### getTime |  |  |  |  |  |  |  |  |  |  | x | x | x |  |  |  |  | X | x
#### getTimestamp |  |  |  |  |  |  |  |  |  |  | x | x | x |  |  |  | x | x | X
#### getAsciiStream |  |  |  |  |  |  |  |  |  |  | x | x | X | x | x | x |  |  |
#### getUnicodeStream |  |  |  |  |  |  |  |  |  |  | x | x | X | x | x | x |  |  |
#### getBinaryStream |  |  |  |  |  |  |  |  |  |  |  |  |  | x | x | X |  |  |
#### getObject | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x

Una "x" indica que el método getXXX se puede utilizar legalmente para recuperar el tipo JDBC dado.

Una "X" indica que el método getXXX está recomendado para recuperar el tipo JDBC dado.

Ozito