2015-07-20 3 views
0

Je semble avoir un problème avec une requête sur un champ CHAR qui est filtré de manière incorrecte lorsque OpenJPA remplace ma valeur constante par un paramètre SQL.Comment puis-je empêcher OpenJPA de remplacer les paramètres "constants" dans mes requêtes?

Exemple

Compte tenu de cette table Oracle

create table PERSON (
    id char(10) not null, 
    type char(3) not null, 
    primary key (id) 
) 

avec trois valeurs différentes pour type: WTW, WAI, V

et l'entité correspondante

@Entity 
public class Person { 
    String id; 
    String type; 
} 

J'utilise la requête suivante à partir d'un fichier orm.xml:

<named-query name="person.v"> 
    <query> 
    select p 
    from Person p 
    where p.type = 'V' 
    </query> 
</named-query> 

Problème

Quand je lance ce grâce à un EntityManager fourni par OpenJPA, les modifications de la requête à

select p.id, p.type 
from PERSON p 
where p.type = ? 

et OpenJPA transmet la valeur "V" en tant que paramètre. La valeur précédemment "constante" pour type est maintenant un paramètre SQL. Le problème réside dans le fait que pour la char(3)type colonne, Oracle va stocker

"V " 

et ce n'est pas égale à la valeur transmise par OpenJPA comme paramètre. Encore une fois: sans paramètres, c'est-à-dire en utilisant simplement la chaîne SQL que j'utilise dans JPQL, tout fonctionne correctement. Je suppose que OpenJPA effectue ce remplacement afin de minimiser le cache de requête en normalisant toutes les requêtes, et je comprends que cela fait une grande différence pour beaucoup de gens, mais je pense que c'est un problème dans mon cas.

Ma question est maintenant: comment puis-je empêcher OpenJPA de faire ce remplacement? Je sais que je n'aurai pas de permutations différentes de cette requête lors de l'exécution. Y a-t-il une propriété de configuration ou un indice de requête que je peux utiliser?

+0

Mise à jour rapide: il n'y a pas de bug dans la façon dont OpenJPA gère les types 'char' dans les instructions préparées. Il ne pouvait tout simplement pas gérer le type de données de la colonne, car nous utilisons un 'PreparedStatement' personnalisé avec un délégué à l'instruction réelle (Oracle), et la détection dans org.apache.openjpa.jdbc.sql, OracleDictionary ([1] (https://github.com/apache/openjpa/blob/2.4.0/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java#L556), [2] (https : //github.com/apache/openjpa/blob/2.4.0/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java#L1253)) ne fonctionne pas. – Kariem

Répondre

0

En plus changeant juste la colonne à un VARCHAR, j'ai deux solutions de contournement qui ne sont pas très agréable:

  1. ADAPT la JPQL à where p.type = 'V ' (« V » suivi de deux espaces).
  2. Utilisez une requête native qui ne sera pas optimisée par OpenJPA.

Dans (1), je sais que sur le sous-jacent char(3) et l'idée de JPQL est de faire abstraction de cette distance, donc cela va un peu contre l'idée d'utiliser JPA. Avec (2) je dois réécrire un peu cette requête simple, mais il ne semble pas juste d'utiliser une requête native juste pour éviter les problèmes créés par les bonnes intentions de mon fournisseur de persistance.