Betrachten Sie die folgende JPA Entity (Implementierung ist Hibernate 4.3.0):Warum funktioniert dieser enum-Parameter für ein einzelnes Feld und nicht für eine Sammlung?
@Entity
public class MyEntity {
@Id
protected long myEntityId;
@Enumerated(EnumType.STRING)
public Condition myCondition = Condition.BAD;
@Enumerated(EnumType.STRING)
@ElementCollection
public Set<Condition> conditions = new HashSet<Condition>();
public enum Condition {
GOOD, FAIR, BAD, SOL
}
}
Wenn ich die folgende Abfrage mit einem Enum-Parameter ausführen, bekomme ich 0 (kein Fehler):
//Produces no results
String queryString = "FROM MyEntity me WHERE :condition MEMBER OF me.conditions";
List<MyEntity> things = JPA.em().createQuery(queryString, MyEntity.class).setParameter("condition", Condition.BAD).getResultList();
Diese Abfrage erzeugt das folgende SQL:
select myentity0_.myentityid as myentity1_38_, myentity0_.mycondition as mycondit2_38_
from MyEntity myentity0_
where ? in (
select conditions1_.conditions
from MyEntity_conditions conditions1_
where myentity0_.myentityid=conditions1_.MyEntity_myEntityId)
Wenn ich stattdessen ein Zeichenfolgenliteral verwende, erhalte ich Ergebnisse. Ich habe auch Ergebnisse, wenn ich die gleichen Parameter Strategie für Nicht-Sammlung Felder verwenden:
// Produces results
queryString = "FROM MyEntity me WHERE 'BAD' MEMBER OF me.conditions";
things = JPA.em().createQuery(queryString, MyEntity.class).getResultList();
// Also produces results
queryString = "FROM MyEntity me WHERE me.myCondition = :condition";
things = JPA.em().createQuery(queryString, MyEntity.class).setParameter("condition", Condition.BAD).getResultList();
//So does this
String queryString = "from MyEntity me join me.conditions c where c = :condition";
List<MyEntity> things = JPA.em().createQuery(queryString, MyEntity.class).setParameter("condition", Condition.BAD).getResultList();
Diese Abfragen erzeugen die folgende SQL:
select myentity0_.myentityid as myentity1_38_, myentity0_.mycondition as mycondit2_38_
from MyEntity myentity0_
where 'BAD' in (
select conditions1_.conditions
from MyEntity_conditions conditions1_
where myentity0_.myentityid=conditions1_.MyEntity_myEntityId)
select myentity0_.myentityid as myentity1_38_, myentity0_.mycondition as mycondit2_38_
from MyEntity myentity0_
where myentity0_.mycondition=?
select myentity0_.myentityid as myentity1_38_, myentity0_.mycondition as mycondit2_38_
from MyEntity myentity0_
inner join MyEntity_conditions conditions1_ on myentity0_.myentityid=conditions1_.MyEntity_myEntityId
where conditions1_.conditions=?
Bin ich in meiner Annahme falsch, dass Hibernate darauf achten sollte EnumType.STRING
und EnumType.ORDINAL
wenn Sie Parameter verwenden? Zumindest ist es inkonsequent. Das Ausfüllen von Parametern funktioniert beim Abfragen von Enum-Feldern, aber nicht beim Auflisten von Auflistungen. Was vermisse ich?
Neben der Antwort, die Sie erhalten haben, können Sie sich immer helfen, indem es tatsächlich Debuggen ... an der SQL-Suche erzeugt ... und Blick auf die JPA-Spezifikation das sagt _Expressions, die einbettbare Typen auswerten, werden nicht in Auflistungsmember-Ausdrücken unterstützt –
@Neil Stockton Was lässt Sie glauben, dass ich die Dinge nicht für mich selbst getestet habe?Sie haben hier in der Frage meinen Versuch, das Problem in einer vereinfachenden Einheit zu isolieren und zu identifizieren. Ich nehme an, ich hätte erwähnen können, dass das von der ersten und dritten JPQL-Abfrage generierte SQL dasselbe ist. Wie für die JPA - Spezifikation zählen Enum - Elemente als eingebettete Elemente? Ich hatte den Eindruck, dass Embeddables im Wesentlichen Unterklassen sind, die als einbettbar kommentiert sind. – Indigenuity
Die Leute können nur kommentieren, was ihnen präsentiert wurde, und die meisten Leute hier präsentieren wenig bis gar kein Debugging, also ist das immer die Annahme. Was Ihr Problem anbelangt, kann ich es (nachdem ich in SELECT {alias} "make it valid JPQL" hinzugefügt habe) in dem JPA-Provider verwenden, den ich verwende (DataNucleus) und er erstellt ein SQL wie 'SELECT * FROM MYENTITY M INNER JOIN MYENTITY_CONDITIONS B0 ON M.ID = B0.MYENTITY_ID WHERE B0.CONDITIONS_ELEMENT = <'BAD'> ', also funktioniert das. Folglich scheint Ihr JPA-Provider das Problem zu sein, nicht Ihr Code –