2010-11-16 13 views
1

La requête suivante JPA ne compile pas:Java JPA "Erreur compilation de la requête" quand il utilise un ENUM

@NamedQuery(name = "PSA.findBySourceSystem", 
    query = "SELECT p FROM PSA p WHERE p.sourceSystem.id = :sourceSystemId") 

p.sourceSystem est le ENUM suivant:

public enum SourceSystem { 
    FIRST(3, "ABC"), SECOND(9, "DEF"), THIRD(17, "GHI"); 

    private int id; 
    private String code; 
    ... 
} 

et est mis en correspondance dans la base de PSA classe:

public class PsaBase implements Serializable { 
    @Column(name = "sourceSystemId") 
    @Enumerated(EnumType.ORDINAL) 
    protected SourceSystem sourceSystem; 
    ... 
} 

La requête compile et fonctionne bien si je re Placez p.sourceSystem.id dans la requête avec quelque chose de plus bénin.

Merci d'avance pour toute aide.

Répondre

2

Il ne devrait pas compiler.

Vous avez à résoudre la valeur ENUM requise manuellement avant de le transmettre comme paramètre de requête:

@NamedQuery(name = "PSA.findBySourceSystem", 
    query = "SELECT p FROM PSA p WHERE p.sourceSystem = :sourceSystem") 

.

public enum SourceSystem { 
    ... 
    private static Map<Integer, SourceSystem> valuesById = new HashMap<Integer, SourceSystem>(); 
    static { 
     for (SourceSystem s: values()) 
      valuesById.put(s.id, s); 
    } 
    public static SourceSystem findById(int id) { 
     return valuesById.get(id); 
    } 
} 

.

em.createNamedQuery("PSA.findBySourceSystem") 
    .setParameter("sourceSystem", SourceSystem.findById(sourceSystemId)); 

EDIT: Depuis sourceSystem est annotés comme @Enumerated(EnumType.ORDINAL), il est stocké dans la base de données comme les nombres ordinaux des valeurs ENUM correspondant donc FIRST est stocké sous forme 0. JPA ne prend pas directement en charge l'utilisation de champs arbitraires de la valeur enum pour l'identifier dans la base de données. Si votre schéma de base de données suppose, vous pouvez faire le tour suivant à découpler état de votre objet à partir du schéma de base de données:

public class PsaBase implements Serializable { 
    protected SourceSystem sourceSystem; 

    @Column(name = "sourceSystemId") 
    public Integer getSourceSystemId() { 
     return sourceSystem.getId(); 
    } 

    public void setSourceSystemId(Integer id) { 
     this.sourceSystem = SourceSystem.findById(id); 
    } 
    ... getter and setter of sourceSystem with @Transient ... 
} 
+0

Merci qui a aidé le compiler, mais maintenant si je passe une valeur SourceSystem avec un identifiant de 3 par exemple, il lie toujours 0. L'identifiant est ce que je recherche dans la requête résultante. –

+0

@David: Mis à jour. – axtavt

+0

Ahh! Je vois cela - je pensais juste que le 0 était une valeur par défaut. Merci beaucoup - c'est tout ce dont j'avais besoin. –