Utilizar Tipos de Datos SQL3

Los tipos de datos comunmente referidos como tipos SQL3 son los nuevos tipos de datos que están siendo adoptados en la nueva versión del estándard ANSI/ISO de SQL. El JDBC 2.0 proporciona interfaces que representan un mapeado de estos tipos de datos SQL3 dentro del lenguaje Java. Con estos nuevos interfaces, podremos trabajar con tipos SQL3 igual que con otros tipos.

Los nuevos tipos SQL3 le dan a una base de datos relacional más flexibilidad en lo que pueden utiizar como tipos para una columna de una tabla. Por ejemplo, una columna podría ahora almacenar el nuevo tipo de dato BLOB (Binary Large Object), que puede almacenar grandes cantidades de datos como una fila de bytes. Una columna también puede ser del tipo CLOB (Character Large Object), que es capaz de almacenar grandes cantidades de datos en formato caracter. El nuevo tipo ARRAY hace posible el uso de un array como un valor de columna. Incluso las nuevas estructuras de tipos-definidos-por-el-usuario (UDTs) de SQL pueden almacenarse como valores de columna.

La siguiente lista tiene los interfaces del JDBC 2.0 que mapean los tipos SQL3. Los explicaremos en más detalle más adelante.

Uitlizar tipos de datos SQL3

Se recuperan, almacenan, y actualizan tipos de datos SQL3 de la misma forma que los otros tipos. Se utilizan los métodos ResultSet.getXXX o CallableStatement.getXXX para recuperarlos, los métodos PreparedStatement.setXXXpara almacenarlos y updateXXX para actualizarlos. Probablemente el 90% de las operacuines realizadas con tipos SQL3 implican el uso de los métodos getXXX, setXXX, y updateXXX. La siguiente tabla muestra qué métodos utilizar:

Tipo SQL3Método getXXXMétodo setXXXMétodo updateXXX
BLOBgetBlobsetBlobupdateBlob
CLOBgetClobsetClobupdateClob
ARRAYgetArraysetArrayupdateArray
Tipo StructuredgetObjectsetObjectupdateObject
REF(Tipo Structured)getRefsetRefupdateRef

Por ejemplo, el siguiente fragmento de código recupera un valor ARRAY de SQL. Para este ejemplo, la columna SCORES de la tabla STUDENTS contiene valores del tipo ARRAY. La variable stmt es un objeto Statement.

ResultSet rs = stmt.executeQuery("SELECT SCORES FROM STUDENTS  	WHERE ID = 2238");
rs.next();
Array scores = rs.getArray("SCORES");
La variable scores es un puntero lógico al objeto ARRAY de SQL almacenado en la tabla STUDENTS en la fila del estudiante 2238.

Si queremos almacenar un valor en la base de datos, utilizamos el método setXXX apropiado. Por ejemplo, el siguiente fragmento de código, en el que rs es un objeto ResultSet, almacena un objeto Clob:

Clob notes = rs.getClob("NOTES");
PreparedStatement pstmt = con.prepareStatement("UPDATE MARKETS
						SET COMMENTS = ? WHERE SALES < 1000000",
						ResultSet.TYPE_SCROLL_INSENSITIVE,
						ResultSet.CONCUR_UPDATABLE);
pstmt.setClob(1, notes);
Este código configura notes como el primer parámetro de la sentencia de actualización que está siendo enviada a la base de datos. El valor CLOB designado por notes será almacenado en la tabla MARKETS en la columna COMMENTS en cada columna en que el valor de la columna SALES sea menor de un millón.

Objetos Blob, Clob, y Array

Una característica importante sobre los objetos Blob, Clob, y Array es que se pueden manipular sin tener que traer todos los datos desde el servidor de la base de datos a nuestra máquina cliente. Un ejemplar de cualquiera de esos tipos es realmente un puntero lógico al objeto en la base de datos que representa el ejemplar. Como los objetos SQL BLOB, CLOB, o ARRAY pueden ser muy grandes, esta característica puede aumentar drásticamente el rendimiento.

Se pueden utilizar los comandos SQL y los API JDBC 1.0 y 2.0 con objetos Blob, Clob, y Array como si estuvieramos operando realmente con el objeto de la base de datos. Sin embargo, si queremos trabajar con cualquiera de ellos como un objeto Java, necesitamos traer todos los datos al cliente, con lo que la referencia se materializa en el objeto. Por ejemplo, si queremos utilizar un ARRAY de SQL en una aplicación como si fuera un array Java, necesitamos materializar el objeto ARRAY en el cliente para convertirlo en un array de Java. Entonces podremos utilizar los métodos de arrays de Java para operar con los elementos del array. Todos los interfaces Blob, Clob, y Array tienen métodos para materializar los objetos que representan.

Tipos Struct y Distinct

Los tipos estructurados y distinct de SQL son dos tipos de datos que el usuario puede definir. Normalmente nos referimos a ellos como UDTs (user-defined types), y se crean con un sentencia CREATE TYPE de SQL.

Un tipo estructurado de SQL se parece a los tipos estructurados de Java en que tienen miembros, llamados atributos, que puede ser cualquier tipo de datos. De echo, un atributo podría ser a su vez un tipo estructurado. Aquí tienes un ejemjplo de una simple definición de un nuevo tipo de dato SQL:

CREATE TYPE PLANE_POINT
(
		X FLOAT,
		Y FLOAT
)
Al contrario que los objetos Blob, Clob, y Array, un objeto Struct contiene valores para cada uno de los atributos del tipo estructurado de SQL y no es sólo un puntero lógico al objeto en la base de datos. Por ejemplo, supongamos que un objeto PLANE_POINT está almacenado en la columna POINTS de la tabla PRICES.
ResultSet rs = stmt.executeQuery("SELECT POINTS FROM PRICES  WHERE PRICE > 3000.00");
while (rs.next()) {
	Struct point = (Struct)rs.getObject("POINTS");
	// do something with point
}
Si el objeto PLANE_POINT recuperado tiene un valor X de 3 y un valor Y de -5, el objeto Struct, point contendrá los valores 3 y -5.

Podríamos haber observador que Struct es el único tipo que no tiene métodos getXXX y setXXX con su nombre como XXX. Debemos utilizar getObject y setObject con ejemplares Struct. Esto significa que cuando recuperemos un valor utilizando el método getObject, obtendremos un Object Java que podremos forzar a Struct, como se ha hecho en el ejemplo de código anterior.

El segundo tipo SQL que un usuario puede definir con una sentencia CREATE TYPE de SQL es un tipo Distinct. Este tipo se parece al typedef de C o C++ en que es un tipo basado en un tipo existente. Aquí tenemos un ejemplo de creacción de un tipo distinct:

CREATE TYPE MONEY AS NUMERIC(10, 2)
Esta definición crea un nuevo tipo llamado MONEY, que es un número del tipo NUMERIC que siempre está en base 10 con dos dígitos después de la coma decimal. MONEY es ahora un tipo de datos en el esquema en el que fue definido, y podemos almacenar ejemplares de MONEY en una tabla que tenga una columna del tipo MONEY.

Un tipo distinct SQL se mapea en Java al tipo en el que se mapearía le tipo original. Por ejemplo, NUMERIC mapea a java.math.BigDecimal, porque el tipo MONEY mapea a java.math.BigDecimal. Para recuperar un objeto MONEY, utilizamos ResultSet.getBigDecimal o CallableStatement.getBigDecimal; para almacenarlo utilizamos PreparedStatement.setBigDecimal.

Características Avanzadas de SQL3

Algunos aspectos del trabajo con los tipos SQL3 pueden parecer bastante complejos. Mencionamos alguna de las características más avanzadas para que las conozcas, pero una explicación profunda no es apropiada para un tutorial básico.

El interface Struct es el mapeo estándard para un tipo estructurado de SQL. Si queremos trabajar fácilmente con un tipo estructurado de Java, podemos mapearlo a una clae Java. El tipo structurado se convierte en una clase, y sus atributos en campos. No tenemos porque utilizar un mapeado personalizado, pero normalmente es más conveniente.

Algunas veces podríamos querer trabajar con un puntero lógico a un tipo estructurado de SQL en vez de con todos los valores contenidos en el propio tipo, Esto podría suceder, por ejemplo, si el tipo estructurado tiene muchos atributos o si los atributos son muy grandes. Para referenciar un tipo estructurado, podemos declarar un tipo REF de SQL que represente un tipo estructurado particular. Un objeto REF de SQL se mapea en un objeto Ref de Java, y podemos operar con ella como si lo hicieramos con el objeto del tipo estructurado al que representa.


Ozito