miércoles, 4 de junio de 2008

JDBC 4.0 y Oracle 11G: combinación ganadora

La versión 4.0 de JDBC, incorporado en Java SE 6.0, supone un salto importante en cuanto a rendimiento en muchos pequeños aspectos. Uno de ellos es la mejora en los pooles, y otro ejemplo -en el que me voy a centrar hoy- son los LOBs. Este artículo no pretende ser un estudio exhaustivo acerca de JDBC 4.0, para eso mejor visitar por ejemplo algunos de los enlaces de abajo (en concreto el de onjava.com o el de ibm-developerworks).

Estas mejoras pueden no ser significativas en algunos/muchos entornos, pero sí que lo son en servidores con mucho estrés o en temas muy concretos como el uso de LOBs, que por fin se pueden gestionar de una forma coherente y sencilla.

Por ejemplo, se han añadido a PreparedStatement los métodos:
/**
* Sets the designated parameter to a InputStream object. The inputstream must contain the number
* of characters specified by length otherwise a SQLException will be
* generated when the PreparedStatement is executed.
* This method differs from the setBinaryStream (int, InputStream, int)
* method because it informs the driver that the parameter value should be
* sent to the server as a BLOB. When the setBinaryStream method is used,
* the driver may have to do extra work to determine whether the parameter
* data should be sent to the server as a LONGVARBINARY or a BLOB
* @param parameterIndex index of the first parameter is 1,
* the second is 2, ...
* @param inputStream An object that contains the data to set the parameter
* value to.
* @param length the number of bytes in the parameter data.
* @throws SQLException if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if a database access error occurs;
* this method is called on a closed PreparedStatement;
* if the length specified
* is less than zero or if the number of bytes in the inputstream does not match
* the specfied length.
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
*
* @since 1.6
*/
void setBlob(int parameterIndex, InputStream inputStream, long length)
throws SQLException;


/**
* Sets the designated parameter to a Reader object. The reader must contain the number
* of characters specified by length otherwise a SQLException will be
* generated when the PreparedStatement is executed.
* This method differs from the setCharacterStream (int, Reader, int) method
* because it informs the driver that the parameter value should be sent to
* the server as a CLOB. When the setCharacterStream method is used, the
* driver may have to do extra work to determine whether the parameter
* data should be sent to the server as a LONGVARCHAR or a CLOB
* @param parameterIndex index of the first parameter is 1, the second is 2, ...
* @param reader An object that contains the data to set the parameter value to.
* @param length the number of characters in the parameter data.
* @throws SQLException if parameterIndex does not correspond to a parameter
* marker in the SQL statement; if a database access error occurs; this method is called on
* a closed PreparedStatement or if the length specified is less than zero.
*
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
* @since 1.6
*/
void setClob(int parameterIndex, Reader reader, long length)
throws SQLException;

Esto implica que, con bases de datos Oracle, nunca más sea necesaria la creación de un blob temporal a través de la API propia de Oracle y posterior asignación a la nueva fila sin que de forma mucho más intuitiva y estándar podemos hacer lo siguiente para insertar datos en una columna de tipo BLOB:
File originalFile = new File(PATH);
Connection conn = ...;
PreparedStatement ps = conn.prepareStatement("...");
ps.setBlob(1, new FileInputStream(originalFile), originalFile.length());
ps.execute();
ps.close();
conn.close();

No sólo es más elegante, sino que en Oracle 11G supone un incremento de hasta un 25% en el rendimiento frente al tradicional método con "BLOB.createTemporary()" propietario de Oracle (son mis datos empíricos con ficheros de más de 10 megas). Lo cual sumado al uso de los nuevos SECUREFILEs para almacenar LOBS, significa que la combinación Java 6 + JDBC 4 + Oracle 11G suponga hasta casi un 50% más de rendimiento que Java SE 1.5 + JDBC 3 + Oracle 10G en la inserción de LOBs de gran tamaño.

Para más información acerca de los cambios que supone JDBC 4 sobre sus antecedores:

No hay comentarios: