2009-12-15 4 views
3

J'ai un peu de mal à utiliser Hibernate avec une colonne char (6) dans Oracle. Voici la structure de la table:Hibernation et remplissage sur la colonne de la clé primaire CHAR dans Oracle

CREATE TABLE ACCEPTANCE 
(
    USER_ID char(6) PRIMARY KEY NOT NULL, 
    ACCEPT_DATE date 
); 

Pour les enregistrements dont l'ID utilisateur a moins de 6 caractères, je peux les choisir sans rembourrage l'ID utilisateur lors de l'exécution des requêtes en utilisant mySQreuiL. C'EST À DIRE. ce qui suit renvoie un enregistrement s'il y a un enregistrement avec un identifiant d'utilisateur "abc".

select * from acceptance where user_id = "abc" 

Malheureusement, lorsque vous effectuez la sélection via Hibernate (JPA), les rendements suivants null:

em.find(Acceptance.class, "abc"); 

Si je pad la valeur cependant, il retourne l'enregistrement correct:

em.find(Acceptance.class, "abc "); 

Le module sur lequel je travaille obtient l'identifiant de l'utilisateur non protégé d'autres parties du système. Y a-t-il un meilleur moyen de faire fonctionner Hibernate que de mettre du code pour adapter l'identifiant de l'utilisateur à une certaine longueur avant de le donner à Hibernate? (qui pourrait présenter des problèmes d'entretien sur la route si la longueur change)

+0

« si la longueur change jamais ». Si cela se produit, votre clé primaire change et vous avez BEAUCOUP plus de problèmes à s'inquiéter. –

Répondre

3

C'est la voie de Dieu de vous dire de ne jamais utiliser CHAR() pour la clé primaire :-)

Sérieusement, cependant, puisque votre user_id est cartographiée sous forme de chaîne dans votre entité dialecte Oracle Hibernate traduit que dans varchar. Comme Hibernate utilise des instructions préparées pour toutes ses requêtes, cette sémantique se poursuit (contrairement à SQuirreL, où la valeur est spécifiée comme littérale et donc convertie différemment).

Basé sur Oracle type conversion rules la valeur de la colonne est ensuite promue à varchar2 et comparée en tant que telle; ainsi vous ne récupérez aucun enregistrement.

Si vous ne pouvez pas modifier le type de colonne sous-jacent, votre meilleure option est probablement d'utiliser la requête HQL et la fonction rtrim() qui est prise en charge par le dialecte Oracle.

+0

J'ai pensé à faire quelque chose comme em.createQuery ("de Acceptance où trim (userId) =: userId"); mais serait-ce vaincre l'index sur la clé primaire? – jthg

+0

Vous n'avez besoin que de 'rtrim()', pas complet 'trim()' - et cela devrait toujours utiliser l'index pour les caractères non-blancs. – ChssPly76

+0

Etes-vous sûr de ça? J'ai trouvé quelques messages de forum sur Google qui disent que rtrim _does_ provoque une analyse de table. – jthg

0

Je ne pense pas. Cependant, vous pouvez définir un UserType pour contenir les dégâts sur un point.

1

Comment se fait-il que votre module obtienne une valeur non capitalisée d'autres parties du système? Si je comprends bien, si l'autre partie du système ne modifie pas le PK, ils devraient lire 6 caractères de la base de données et passer 6 caractères tout au long du chemin - ce serait OK. La seule exception serait lorsqu'un PK est généré, auquel cas il peut être nécessaire de le compléter.

Vous pouvez contourner le problème (en réduisant ou en complétant la valeur chaque fois que cela est nécessaire), mais cela ne résoudra pas le problème dès le départ, car votre PK n'est pas géré de manière cohérente.Pour résoudre le problème dès le départ, vous devez eiher

  • reçoivent toujours 6 caractères des autres parties du module
  • utilisation varchar2 pour traiter correctement la taille dynamique

Si vous ne pouvez pas résoudre le problème dès le départ, alors vous aurez besoin en effet soit

  • ajouter parage/rembourrage tout autour de la place si nécessaire
  • ajouter parage/rembourrage dans le DAO si vous avez un
  • ajouter parage/rembourrage dans le type d'utilisateur si cela fonctionne (suggestion de N. Hughes)
+0

Je dirais même si le type DB est un CHAR (6) alors il s'attend sémantiquement que les clients de cette DB travaillent avec 6 caractères, point. Donc soit la définition de la base de données doit être modifiée, soit les clients doivent se conformer :) – Romain

Questions connexes