Hibernate 3 y los tipos de datos para cadenas largas

1
36457

Hibernate
3 y los tipos de datos para cadenas largas

Creación: 22-03-2007

Introducción

En este tutorial quiero contaros la
experiencia que he tenido a la hora de manejar los diferentes tipos
de datos existentes para grandes cadenas de texto, tales como el tipo
Clob de Oracle, o los tipos TEXT de MySQL y SQLServer, utilizando la
última versión de Hibernate para su lectura y
escritura.

Entorno

El tutorial está escrito
usando el siguiente entorno:

  • Hardware: HP COMPAQ Presario
    V6000 (Centrino Duo 1.66GHz, 2048 MB RAM, 100 GB HD)

  • Sistema Operativo: Windows
    Vista Bussiness

  • Máquina Virtual Java:
    JDK 1.6.0 de Sun Mircosystems

  • Oracle 9.2.0.1.0

  • Oracle 10g Express Edition

  • SQL Server 2005 Express
    Edition

  • MySQL 5.0

  • Hibernate 3.2.1

Campos TEXT

Resultó
bastante fácil configurar hibernate para acceder a campos TEXT
de las bases de datos SQL Server 2005 y MySQL 5.0, ya que no
encontramos ningún tipo de incompatibilidad de lectura o
escritura.

Consultando
la documentación de Hibernate, vemos que estos campos son
mapeables directamente a un tipo de dato “text”. Os lo
muestro a continuación:

<?xml
version=«1.0»
encoding=«UTF-8»?>

<!DOCTYPE
hibernate-mapping PUBLIC
«-//Hibernate/Hibernate Mapping DTD
3.0//EN»

«http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd»>

<hibernate-mapping>

<class
name=«com.autentia.hibernate.Test»
table=«Test»>

<id
name=«id»
type=«java.lang.Integer»/>

<property
name=«text»
type=«text»
/>

</class>

</hibernate-mapping>

Únicamente
tenemos que recoger su valor en nuestra clase pojo a String, y la
lectura y la escritura en la base de datos correspondiente se realiza
correctamente.

package
com.autentia.hibernate;

public
class
Test {

private
int
id;

private
String
text;

public
int
getId() {

return
id;

}

public
void
setId(
int
id) {

this.id
= id;

}

public
String getText() {

return
text;

}

public
void
setText(String text) {

this.text
= text;

}

}

Campos CLOB

La
compatibilidad de Hibernate con campos de tipo CLOB lleva dando
problemas desde los inicios, problemas achacables en todo momento a
los drivers de Oracle. Por tanto nos decidimos a probarlo tanto en la
versión 9i y la 10g de la base de datos de Oracle. En concreto
en las versiones Oracle 9.2.0.1.0i y Oracle Express Edtion 10g,
utilizando los correspondientes drivers disponibles en la página
de Oracle.

Total
compatibilidad con Oracle 10 g y driver jdbc para Oracle versión
10g

Consultando
la documentación de Hibernate vemos que el mismo tipo de dato
anterior, “text”, es válido también para
mapear los tipos CLOB de Oracle, y he podido comprobar que es cierto.

Utilizando
el mismo mapeo que para los campos TEXT de MySQL y SQLServer, no
tenemos ningún problema en leer y escribir en campos de tipo
CLOB en Oracle 10g:

<?xml
version=«1.0»
encoding=«UTF-8»?>

<!DOCTYPE
hibernate-mapping PUBLIC
«-//Hibernate/Hibernate Mapping DTD
3.0//EN»

«http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd»>

<hibernate-mapping>

<class
name=«com.autentia.hibernate.Test»
table=«Test»>

<id
name=«id»
type=«java.lang.Integer»/>

<property
name=«text»
type=«text»
/>

</class>

</hibernate-mapping>

Únicamente
tenemos que recoger su valor en nuestra clase pojo a String (como en
el ejemplo anterior), y la lectura y la escritura en la base de datos
se realiza correctamente.

Debo
incidir en el hecho de que se utiliza el driver jdbc de oracle para
la versión 10g, ya que, como vamos a poder comprobar a
continuación, el driver para las versiones 9i tiene problemas
de compatibilidad.

Problemas
con Oracle 9i

He
comprobado los problemas que existen con el driver jdbc de oracle
para versiones 9i. No se ha podido acceder a los campos CLOB ni
siguiendo las instrucciones propuestas en el foro de Hibernate
(http://www.hibernate.org/56.html) ni usando otras alternativas
encontradas por la red. Ésto puede ser debido a que las
soluciones propuestas son para versiones anteriores a Hibernate 3,
pero no estoy seguro.

Me
decido entonces a probar con el driver para 10g de oracle. Pruebo a
mapear el campo con un tipo “text”, como en los ejemplos
anteriores. La escritura en la base de datos se realiza
correctamente, pero a la hora de la lectura, obtenemos siempre una
cadena vacía como resultado.

Probamos
entonces a mapear a un tipo de dato Clob (java.sql.Clob):

<?xml
version=«1.0»
encoding=«UTF-8»?>

<!DOCTYPE
hibernate-mapping PUBLIC
«-//Hibernate/Hibernate Mapping DTD
3.0//EN»

«http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd»>

<hibernate-mapping>

<class
name=«com.autentia.hibernate.Test»
table=«Test»>

<id
name=«id»
type=«java.lang.Integer»/>

<property
name=«text»
type=«java.sql.Clob»
/>

</class>

</hibernate-mapping>

Debemos
cambiar nuestro pojo para recoger el dato correctamente:

package
com.autentia.hibernate;

public
class
Test {

private
int
id;

private
java.sql.Clob
text;

public
int
getId() {

return
id;

}

public
void
setId(
int
id) {

this.id
= id;

}

public
java.sql.Clob getText() {

return
text;

}

public
void
setText( java.sql.Clob text) {

this.text
= text;

}

}

Tampoco
resuelve nuestro problema. La escritura se realiza correctamente,
pero la lectura nos sigue devolviendo una cadena vacía. Se
prueba lo mismo mapeando a oracle.sql.Clob, con idéntico
resultado.

Alternativa
propuesta

Básicamente
nuestro problema es que queremos guardar una cadena de una longitud
considerable (mensaje de correo, carta, etc.), en un campo de una
base de datos Oracle. Tenemos la opción de utilizar un campo
de tipo LONG (almacena cadenas de hasta 2GBytes, la mitad que un
CLOB, pero es suficiente). El mapeo de Hibernate 3 fuciona
perfectamente tanto para Oracle 10g como para Oracle 9i, utilizando
nuestro tipo de dato “text” como en los ejemplos
anteriores.

La
lectura y la escritura en la base de datos se realiza correctamente y
su tamaño es lo suficientemente grande para resolver nuestro
problema.

Conclusiones

Si
queremos acceder a un campo CLOB y estamos usando una versión
10g, no nos vamos a encontrar ningún problema al usar
Hibernate 3. Si usamos una versión 9i o anterior recomendamos
usar la alternativa del campo LONG.

Desde
Autentia, los creadores del web www.adictosaltrabajo.com,
recomendamos usar software libre para todos nuestros desarrollos.
Como apoyo al software libre acabamos de liberar una herramienta de
gestión de empresas bajo licencia GPL, esperamos que os guste.
La podés obtener en
http://sourceforge.net/projects/tntconcept.

Código

Os
he dejado el código fuente aquí,
con todo lo necesario para acceder desde Hibernate 3 a los campos
TEXT de MySQL y SQLServer2005, y al campo LONG de Oracle. También
sirve de ejemplo para poder ver como usar hibernate con varios
gestores de datos a la vez. Que os aproveche.

El
proyecto ha sido preparado con maven, para facilitar la descarga de
las librerías necesarias.

Desde
Autentia sabemos que no se puede saber todo, si alguién ha
sido capaz de solucionar el problema accediendo desde Hibernate 3 a
un campo CLOB en una base de datos Oracle 9i, tiene disponible ésta
web para ayudarnos a todos.

Sobre el autor

José
Carlos López Díaz

mailto:jclopez@autentia.com

Autentia Real Business Solutions
S.L – “Soporte a Desarrollo”

1 Comentario

  1. Hola,
    Creo que esto que voy a comentar tiene que ver con el tutorial 🙂

    Yo tengo un String (de java) con unos 2000 caracteres que son unos 2500 Bytes (UTF8), cuando intento guardar esto en la base de datos, en un varchar2(4000) me da este error: ORA-01461: can bind a LONG value only for insert into a LONG column.
    Lo cual me hace pensar que Hibernate está mapeando mi String a LONG de Oracle :S
    Lo que mas me mosquea es que la mayoría de las entities que hacen uso de este campo varchar2(4000) admiten el texto, pero hay algunas que no. Por mas que miro el código no veo la diferencia con unas y otras.
    ¿Porque mapea a LONG?

    Gracias y un saludo.

Dejar respuesta

Please enter your comment!
Please enter your name here