Desarrollo de Java con LOBs en DB2 Universal Database

Este artículo utiliza un ejemplo del mundo real para mostrarle cómo utilizar tipos de datos de objetos grandes con DB2 Universal Database en su desarrollo de Java.

Introducción

Los objetos de datos grandes, como las imágenes y archivos de audio, frecuentemente necesitan ser almacenados en una base de datos. DB2® Universal DatabaseTM proporciona tipos de datos especializados para almacenar objetos de datos grandes. Estos tipos de datos son conocidos como objetos grandes (LOBs). En este artículo, exploraremos el mundo de los LOBs. Más específicamente, exploraremos los LOBs desde la perspectiva de un desarrollador de Java. Verá cómo es posible almacenar y recuperar LOBs en sus aplicaciones de Java.


El escenario empresarial

Siempre es útil aplicar su aprendizaje a un ejemplo del mundo real. En consecuencia, en este artículo vamos a pretender que estamos en una librería. Queremos poder presentar nuestro sitio web a los visitantes en una forma que les permita recuperar una imagen de la portada de nuestros libros. Después, verá cómo podemos almacenar nuestras imágenes de portada como BLOBs. También, queremos poder almacenar resúmenes de libros en la base de datos, de forma que puedan ser buscados por palabras clave. Como verá, nuestro tipo de datos de preferencia será un CLOB. El diagrama a continuación le dará una idea del flujo de trabajo que conseguiremos en este artículo.

Figura 1
Figure 1

La familia de LOBs de tipos de datos

DB2 proporciona tres tipos distintos de datos de objetos grandes. Todos estos tipos de datos pueden almacenar hasta 2 gigabytes de datos:

  • CLOB (Character Large Object) - puede contener hasta 2 gigabytes de datos de caracteres
  • BLOB (Binary Large Object) - puede contener hasta 2 gigabytes de datos binarios. Estos datos binarios pueden, en esencia, ser cualquier cosa (por ejemplo, una imagen, un archivo de audio, etc.).
  • DBCLOB (Double-Byte Character Large Object) - puede contener hasta 2 gigabytes de datos de caracteres de doble byte. Tome en cuenta que este tipo de datos sólo debe ser utilizado si la base de datos que creó fue configurada para datos de doble byte.

Estos tipos de datos caen bajo la sombrilla de los tipos de datos SQL3. Como verá más adelante en este artículo, JDBC 2.0 tiene soporte para estos tipos de datos.


No lo mueva si no tiene que hacerlo

Mover objetos grandes en la memoria puede ser una operación que requiera muchos recursos. En consecuencia, DB2 proporciona dispositivos para interactuar con LOBs que puedan minimizar dicho movimiento.


¿Dónde están mis datos?

Uno de los principales puntos de interés que debemos tener en cuenta sobre los LOBs en DB2 es que los valores de los LOBs no son almacenados en una tabla de base de datos. Lo que en realidad se almacena es un descriptor. Este descriptor apunta hacia la ubicación real del LOB. Los valores reales del LOB son almacenados en espacios de tabla. Los espacios de tabla son unidades de almacenamiento físico.


Ubicadores para representar sus valores de LOB

Lo que en realidad es almacenado en una columna de un LOB no son los datos reales del LOB, sino un puntero hacia los datos del LOB. Este puntero es conocido como un "ubicador". Estos ubicadores son utilizados para representar sus valores de LOB. Cuando recupera datos en un Conjunto de Resultados, estará recuperando ubicadores y no los valores reales del LOB que representan. Como verá, tiene que pedir explícitamente los valores del LOB para que sean recuperados. En la jerga de las bases de datos, esta recuperación es conocida como "materialización".


Estableciendo las cosas

Iniciemos de una vez y usemos el DB2 Command Line Processor para realizar nuestra experimentación de LOB.

Comenzaremos por crear una base de datos llamada "LOBDB":

db2 => create database LOBDB

Nos conectaremos a la base de datos utilizando el nombre de usuario db2admin y la contraseña db2admin:

db2 => connect to LOBDB user db2admin using db2admin

Para propósitos de nuestro aprendizaje, crearemos un par de tablas: una que almacenará un BLOB y otra que almacenará un CLOB:

db2 => create table bookcovers (bookisbn varchar(10) not null, bookcover blob (100K)
not null, primary key(bookisbn))

db2 => create table abstracts (bookisbn varchar(10) not null, bookabstract clob (100K)
not null, primary key(bookisbn))

Los valores de 100K en las sentencias anteriores son una declaración de la longitud máxima de los LOBs que queremos almacenar. De nuevo, esta longitud puede variar desde un byte hasta 2 gigabytes. Esta información de máxima longitud es utilizada por su programa de aplicación para asignar un almacenamiento intermedio adecuadamente dimensionado para alojar datos conforme se van materializando.

Es posible utilizar los siguientes sufijos para representar el número de bytes de longitud:

K: kilobytes (1.024 bytes)
M: megabytes (1.048.576 bytes)
G: gigabytes (1.073.741.824 bytes)

En nuestras dos tablas, nuestros libros son diferenciados por la clave primaria de bookisbn, la cual es una representación de columna del número ISBN de un libro.


¿Compactar o no compactar?

Al crear una tabla, es posible especificar las opciones COMPACT o NOT COMPACT. Si la opción COMPACT es especificada, entonces los datos del LOB que almacene requerirán una cantidad mínima de espacio. Sin embargo, si realiza una actualización en la columna del LOB que incremente el tamaño del LOB almacenado, se aplica una pena de rendimiento. En cambio, si especifica NOT COMPACT (el valor predeterminado), sus valores de LOB en esencia tendrán el camino libre para crecer.


¿Con registro o sin registro?

Si especifica la opción LOGGED, entonces las actualizaciones a una columna de LOB son registradas en el registro del sistema. Especificar la opción LOGGED proporciona la mayor protección para los datos que están almacenados, de forma que puedan ser reconstruidos en caso de que surja un fallo en el soporte físico con un proceso de recuperación en avance. Sin embargo, esto tiene un costo cuando se trata del espacio en disco (además de los costos de tiempo asociados con el hecho de grabar en el disco). Si no especifica una, la opción LOGGED será elegida de forma predeterminada.


Insertando LOBs

La inserción de un BLOB mediante Java es bastante sencilla. Eche un vistazo a la muestra de código a continuación:

Haga clic para ver la lista de códigos

 PreparedStatement preparedStatement =
				connection.prepareStatement("INSERT INTO BOOKCOVERS VALUES(?,?)"); File imageFile =
					nuevo File("c:\\redbookcover.jpg"); InputStream inputStream =
					nuevo FileInputStream(imageFile); preparedStatement.setString(1,"
				0738425826");
				preparedStatement.setBinaryStream(2,inputStream,(int)(imageFile.length()));
				preparedStatement.executeUpdate();

El pequeño fragmento de código anterior toma un archivo llamado redbookcover.jpg , ubicado en la raíz de la unidad C, y lo almacena en la base de datos. Note cómo asociamos nuestro archivo con un InputStream. Este objeto InputStream es utilizado para llenar el valor de la sentencia preparada que representa nuestra columna de BLOB. Este código y el otro código en este artículo pueden ser encontrados en el archivo zip del proyecto asociado con este artículo.

La inserción de un CLOB es casi idéntica a la inserción del BLOB mostrado anteriormente. Es posible ver esto en el archivo del proyecto llamado ClobInsertion.java. Como verá en el archivo ClobInsertion.java , almacenamos el resumen de nuestro libro en la forma de un CLOB. Este resumen es obtenido de un archivo de texto llamado redbookabstract.txt.


Recuperando LOBs

Ya hemos insertado algunos LOBs. ¿Ahora cómo los recuperamos en Java? Este, de nuevo, es un proceso bastante sencillo.

Haga clic para ver la lista de códigos

 PreparedStatement preparedStatement = connection.prepareStatement(
				"SELECT BOOKCOVER FROM BOOKCOVERS WHERE BOOKISBN=?"); preparedStatement.setString(1,
				"0738425826"); ResultSet resultSet = preparedStatement.executeQuery(); while
				(resultSet.next()) { // materialization of the Blob Blob blob =
				resultSet.getBlob(1); InputStream inputStream = blob.getBinaryStream(); File
				fileOutput = nuevo File("C:\\clonedredbookcover.jpg"); FileOutputStream fo =
					nuevo FileOutputStream(fileOutput); int c; while ((c =
				inputStream.read()) != -1) fo.write(c); fo.close(); System.out.println("Blob
				retrieved");

En el segmento de código anterior, ejecutamos una sentencia preparada en la cual seleccionamos el BLOB que insertamos en el segmento de código anterior. Lo que se debe tener en cuenta es que el BLOB real no se materializa hasta la línea:

InputStream inputStream = blob.getBinaryStream();

Utilizamos nuestra secuencia de entrada para almacenar nuestro BLOB recuperado en un archivo llamado clonedredbookcover.jpg.

Para recuperar los CLOBs, la mayoría de la sintaxis es similar a la que se usa para recuperar un BLOB. Eche un vistazo al archivo del proyecto ClobRetrieval.java.

La API de JDBC nos proporciona los medios para hacer algunas cosas interesantes con nuestro CLOB.

Vea el código a continuación:

Haga clic para ver la lista de códigos

 Clob clob = resultSet.getClob(1); //retrieve the first 200
				characters String subString = clob.getSubString(1,200); System.out.println("First
				200 characters of Clob (Book Abstract): + subString); // find the position of a
				given String in the Clob long positionOfString = clob.position("tool",1);
				System.out.println("Position of SubString: + positionOfString);

En el código anterior, utilizamos el método getSubString para obtener una porción de nuestro CLOB almacenado. Dicha función puede ser utilizada por programas de aplicación de cliente que tal vez sólo quieran una porción de nuestro resumen del libro. El uso del método posición también es demostrado. Si una secuencia dada está presente dentro de nuestro CLOB, nuestro método retornará una larga que representa la posición inicial de la serie que está siendo buscada; si no es así, se retornará un -1. El método de posición de la interfaz del CLOB funciona sin materializar los datos almacenados.

La materialización real del CLOB ocurre con el código:

Haga clic para ver la lista de códigos

 File fileOutput = ;new;
				File("C:\\clonedredbookabstract.txt"); FileOutputStream fo = ;new;
				FileOutputStream(fileOutput); InputStream is = clob.getAsciiStream(); int c;
					while; ((c = is.read()) != -1) fo.write(c); fo.close();

En el fragmento anterior, materializamos nuestro CLOB almacenado en un nuevo archivo llamado clonedredbookabstract.txt. Hacemos esto al utilizar el método getAsciiStream de nuestro CLOB. Así como lo hicimos al recuperar nuestro BLOB, asignamos la secuencia a un InputStream que después leemos y a su vez escribimos lo que leemos en nuestro FileOutputStream.


Conclusión

En este artículo, ha visto cómo DB2 UDB proporciona los recursos para almacenar grandes objetos de datos. Utilizando la API de JDBC 2.0, es posible interactuar con LOBs mediante Java. Este artículo le ha mostrado el uso de la API de JDBC. Lo hicimos al presentarle un ejemplo del mundo real sobre una librería que necesitaba almacenar imágenes de portadas de libros y resúmenes de libros. Ahora se debe sentir cómodo con el uso de LOBs en sus propias aplicaciones de Java.


Agradecimientos

Me gustaría agradecer a Robert Indrigo por su ayuda para revisar este artículo.


Aviso Legal

Este artículo contiene código de muestra. IBM le otorga ("Licenciatario") una licencia no exclusiva y libre de regalías para utilizar este código de muestra. Sin embargo, el código de muestra es proporcionado como está y sin ninguna garantía, EXPRESA O IMPLÍCITA, INCLUYENDO A CUALQUIER GARANTÍA IMPLICADA DE COMERCIALIZACIÓN, ADECUACIÓN PARA UN PROPÓSITO PARTICULAR O NO INFRACCIÓN. IBM Y SUS LICENCIANTES NO SERÁN RESPONSABLES POR CUALQUIER DAÑO SUFRIDO POR EL LICENCIATARIO QUE RESULTE DE SU USO DEL SOFTWARE. EN NINGÚN CASO IBM O SUS LICENCIANTES SERÁN RESPONSABLES POR CUALQUIER PÉRDIDA DE INGRESOS, GANANCIAS O DATOS, O POR DAÑOS DIRECTOS, INDIRECTOS, ESPECIALES, CONSECUENTES, INCIDENTALES O PUNITIVOS CAUSADOS DE CUALQUIER FORMA Y SIN IMPORTAR LA TEORÍA DE RESPONSABILIDAD, QUE SURJA DEL USO O LA INCAPACIDAD PARA USAR EL SOFTWARE, AÚN SI IBM HA SIDO PREVIAMENTE NOTIFICADO DE LA POSIBILIDAD DE DICHOS DAÑOS.

IBM, DB2 y DB2 Universal Database son marcas registradas de IBM Corporation en los Estados Unidos, otros países o ambos.

Windows es una marca registrada de Microsoft Corporation en los Estados Unidos, otros países o ambos.

Java y todas las marcas y logotipos basados en Java son marcas registradas de Sun Microsystems, Inc. en los Estados Unidos, otros países o ambos.

UNIX es una marca registrada de The Open Group en los Estados Unidos y otros países.

Otros nombres de compañías, productos y servicios pueden ser marcas registradas o marcas de servicio de otros.

Información de coypright y marcas registradas de IBM


Descargar

DescripciónNombretamaño
Código de ejemplolobprojectfiles.zip  ( HTTP | FTP )28KB

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=Information mgmt
ArticleID=964022
ArticleTitle=Desarrollo de Java con LOBs en DB2 Universal Database
publish-date=01212013