2010-08-16 5 views
6

Bonjour les gars, j'ai des problèmes avec des correspondances exactes en faisant un NamedQuery.JAVA: Problème de chaîne NamedQuery

J'utilise actuellement quelque chose comme ceci:

@NamedQuery(name = MyClass.GET_ENTRY_BY_NAME, query = "select e from Entry e where e.name =:"+ Entry.NAME) 

... 

Query query = em.createNamedQuery(MyClass.GET_ENTRY_BY_NAME); 
     query.setParameter(Entry.NAME, myEntry.getName()); 

Il travaille pour la plupart des cas, mais je remarquai que dans le cas où l'utilisateur passe le nom de fichier avec un espace à la fin, l'namedQuery ignore ce caractère. Par exemple:

Query query = em.createNamedQuery(MyClass.GET_ENTRY_BY_NAME); 
     query.setParameter(Entry.NAME, myEntry.getName()+ " "); 

Renvoie le même résultat que la requête précédente. Contournement de ma validation 'entry valide'. En d'autres termes, j'aimerais que la requête ne retourne aucune entrée et traite l'erreur plus tard.

Une solution que je pouvais penser, est de mettre des guillemets simples autour de mon paramètre dans la namedQuery, comme ceci:

@NamedQuery(name = MyClass.GET_ENTRY_BY_NAME, query = "select e from entry e where e.name =':"+ Entry.NAME "'") 

Cependant, il plantera mon code dans le cas où la chaîne contient des guillemets simples en elle ..

Des idées les gars?

Répondre

4

J'ai fait des recherches dans JPA et a découvert qu'il fait un peu de coupe automatique pour Chars, je Je ne suis pas sûr si cela se comporte de la même manière avec les cordes, mais comme cela m'arrive ... je le crois. La seule façon de le contourner consiste à définir un attribut dans l'objet DatabaseLogin de session (voir http://www.eclipse.org/eclipselink/api/1.1/org/eclipse/persistence/sessions/DatabaseLogin.html#setShouldTrimStrings). Eh bien, je ne voulais pas me tromper avec les propriétés de la session, alors j'ai décidé de faire une sorte de vérification et de lancer la même exception que la capture NoResultException dans mon code.

je essentiellement pris le résultat de la base de données et le champ par rapport à la chaîne je:

query.setParameter(Entry.NAME, myEntry.getName()); 

... 

if(!StringUtils.equals(result.getName(), myEntry.getName()){ 
    do a cool throw just like NoResultException Catch 
} 

Je devais aussi inclure la fonction Trim axtavt! Ceci est juste pour s'assurer que si la base de données a une colonne avec des espaces de fin et qu'elle correspond au paramètre donné par l'utilisateur, elle sera incluse comme réponse valide. Par exemple:

Entrée de base de données: Nom = "Flavio" - Ajusté avec la fonction = "Flavio".

Paramètre transmis: Nom = "Flavio" - Découpé par la fonction automatique JPA = "Flavio".

Si elle n'est pas tronquée du tout, il suffit de comparer "Flavio" avec "Flavio", en retournant NoResult quand il était censé retourner cette entrée.

Null solution de contournement, mais tant qu'il n'y a pas d'autre moyen d'arrêter l'auto-rognage, nous devrons simplement faire usage de ce genre de choses.

Merci pour toutes les autres réponses !!

4

Je suppose que cela se produit parce que votre champ de base de données est déclaré comme CHAR(...), et donc les valeurs stockées sont remplies avec des espaces qui ne sont pas pris en compte par l'opération =.

Ainsi, vous pouvez soit déclarer votre champ de base de données VARCHAR(...) ou utiliser une fonction trim intégrée:

query = "select e from Entry e where trim(trailing from e.name) =:"+ Entry.NAME 
+0

Salut axtavt, merci pour la rapidité de la réponse! Eh bien, ma base de données est définie sur VARCHAR. Mais je ne suis pas sûr si la version MySql a quelque chose à voir avec ce problème. J'ai également pensé à faire quelques ajustements avant de définir le paramètre pour la requête, mais je voulais que le logiciel renvoie une erreur pour tout ce qui est différent de la base de données, assurant que l'utilisateur saisit exactement ce qu'il voulait. –

+0

@flavio: Je ne suis pas familier avec MySQL, donc je ne peux rien dire sur ses fonctionnalités. Notez également que mon exemple de requête tronque la valeur stockée, pas le paramètre, de sorte que le résultat doit être exact. – axtavt

+0

J'ai débogué le code en vérifiant le processus de construction de la requête ... Avec le code que vous avez fourni, il semble que le problème soit dans mySql. J'ai remarqué que les deux paramètres et l'entrée de la base de données sont différents ... cependant pour une force divine mystique inconnue, MySql ne fait que tronquer les espaces et les considérer exactement comme des allumettes ... Maintenant, je pense avoir des recherches à faire pour voir si c'est vraiment un comportement attendu MySql ou il y a quelque chose d'autre derrière. Pour l'instant, je pense que je vais devoir faire des vérifications supplémentaires. Merci! –