2010-07-05 3 views
3

Quelqu'un at-il entendu parler de cette erreur avant:Hibernate + Oracle + Clob: Contenu des attributs se commutée

J'ai une application Java 5, qui utilise Hibernate 3.3.2 pour accéder à une base de données Oracle 10g, le pilote JDBC est la version du pilote de lumière Oracle 10.2.0.4.0 (la version la plus récente, je pense). L'accès à la base de données se fait lors d'une transaction gérée via les outils AOP du printemps. Il y a une table de base de données mappée à une entité Java, le mappage est effectué via des annotations. Il y a deux attributs dans cette entité qui sont CLOB dans la base de données. Ils sont annotés selon JPA avec "Lob" et sont Java Strings. Everthing fonctionne correctement sauf si les deux attributs ont des valeurs de plus de 4000 caractères: Après la validation, les valeurs sont activées dans la base de données, c'est-à-dire que l'attribut A contient la valeur de l'attribut B et vice versa.

Ce n'est pas une blague!

Le débogueur Eclipse me dit que l'entité Java a les valeurs correctes jusqu'à la fermeture de la transaction (je n'ai pas débogué dans la gestion des transactions de printemps). Cette erreur ne se produit pas si les deux Clobs sont annotés avec l'annotation Hibernate 'Type (type = "clob")' (auquel cas ils doivent être du type java.sql.Clob et non String, bien sûr).

Répondre

0

En attendant, je trouve une solution au problème: Le SQL dialecte était mal, quelqu'un mis à Oracle9 au lieu de la version correcte, qui est ceci:

name = valeur "hibernate.dialect" = "org.hibernate.dialect.Oracle10gDialect"

Réglage du SQL-dialecte correct résout le problème :-)

0

Je ne suis pas sûr à 100% mais pourriez-vous essayer de définir la propriété de connexion SetBigStringTryClob à true (voir How To Handle CLOBs Easily in JDBC?).

Si vous utilisez Spring, quelque chose comme ceci:

<property name="hibernateProperties"> 
    <props> 
    <prop key="hibernate.connection.SetBigStringTryClob">true</prop> 
    </props> 
</property> 
+0

Oui, merci, qui est censé corriger les erreurs avec plus de 32 Ko dans un CLOB-Attribute, je l'ai fait essayer en vain. Il y a plusieurs questions ici sur stackoverflow et ailleurs sur les problèmes avec un seul attribut CLOB et un contenu supérieur à 4000 caractères ou plus. J'espère que je les ai tous trouvés :-) Notez que mon problème se produit seulement quand au moins deux attributs ont plus de 4000 caractères. –

+0

@Tim TBH, c'était plus un tir dans l'obscurité.En fait, votre cas est vraiment étrange (et je me demande * qui * échange les valeurs) et sent comme un méchant bug quelque part. Ajoutant cette question à mon préféré pour suivre cette histoire. –

+0

Je suppose que a) les valeurs CLOB nécessitent un traitement spécial si elles contiennent plus de 4000 caractères, et b) Hibernate ou le pilote Oracle JDBC a une erreur qui change les valeurs s'il y en a plusieurs qui ont besoin de cette gestion supplémentaire. Mais je ne peux pas me permettre le temps de déboguer les deux, et je n'ai pas trouvé de bogue similaire dans la DB d'Hibernate. (Je ne peux pas simplement mettre à jour Hibernate, parce que le logiciel est utilisé en production et changer toute la distribution d'Hibernate nécessiterait un test complet de l'ensemble du logiciel). –

0

J'ai exactement le même problème. Deux CLOB sur une table. Sur l'insert, seul un est réglé et tout va bien. Sur la mise à jour, j'ai mis le second et après validation, les valeurs sur la table sont permutées. Les deux contiennent plus de 4000 caractères. Débogué et les valeurs sur le bean sont correctes. La chose triste est que j'ai déjà org.hibernate.dialect.Oracle10gDialect dans mes propriétés. (version Hibernate 4.2.2.Final)

// UPDATE pour l'instant comme une solution de contournement je définir la première colonne en tant que actualisable = false dans l'annotation APP de sorte que lors de la génération de la requête de mise à jour par hiberner il n'y a qu'une seule colonne CLOB maintenant. Je peux le faire car dans ce cas particulier, je n'ai pas besoin de changer la valeur après l'insertion, mais ce n'est pas une solution générale.

0

La seule chose qui a fonctionné pour nous était d'utiliser des requêtes hql pour la mise à jour. Chaque requête mis à jour un CLOB (donc nous avons besoin de deux requêtes distinctes):

Query query = em.createQuery("update SomeTable as someTable set value = :value where id = :id"); 
query.setParameter("value", value); 
query.setParameter("id", id); 
if (query.executeUpdate() != 1) { 
    throw new Exception("Value update had no effect"); 
} 
Questions connexes