2016-04-19 17 views
0

Ich versuche, ein Prädikat zu schreiben, in dem nur Objekte der Klasse Mitarbeiter zurückgegeben werden, wenn sie mehr als 1 Manager haben. Es sollte true zurückgeben, wenn es mehr als 1 Manager für diesen Angestellten gibt, und false, wenn es 0 oder 1 gibt. Das Gesamtergebnis sollte gegen einen booleschen Wert geltend gemacht werden, der die Filteroption angibt, die der Benutzer ausgewählt hat, aber um die Dinge einfach zu halten habe die Variable in der letzten Zeile durch den hartcodierten Wert true ersetzt. Der Code sieht wie folgt aus:greaterDie Abfrage löst unerwarteten AST-Knoten in der Nähe>

public Predicate toPredicate(final Root<Employee> employeeRoot, final CriteriaQuery<?> query, final CriteriaBuilder cb) { 
    final Subquery<Long> subquery = query.subquery(Long.class); 
    final Root<EmployeeManager> employeeManagerRoot = subquery.from(EmployeeManager.class); 
    subquery.select(cb.count(employeeManagerRoot)); 
    subquery.where(cb.equal(employeeManagerRoot.get("employee"), employeeRoot.<Long> get("id"))); 

    return cb.equal(cb.greaterThan(subquery, Long.valueOf(1)), true); 
} 

jedoch der folgende Fehler erzeugt wird, wenn man versucht, diesen Code auszuführen:

Verursacht durch: org.hibernate.hql.internal.ast.QuerySyntaxException: unerwartet AST-Knoten:> nahe Linie 1, Spalte 453 [Wählen Sie generatedAlias0 aus com.test.domain.core.entities.Employee als generatedAlias0, wobei ( generatedAlias0.id in (select generatedAlias1.employee.id aus com.test.domain. core.entities.EmployeeManager als generatedAlias1 wobei generiert wird Alias1.manager = 1 l)) und ((select count (generatedAlias2) von com.test.domain.core.entities.EmployeeManager als generatedAlias2 wo generatedAlias2.employee = generatedAlias0.id)> 1L =: param0)

Ich habe versucht, die SQL, die in der Ausnahme ausgegeben wurde, direkt in die Datenbank zu laufen, und es scheint, die richtigen Werte zurückzugeben! Wie Sie jedoch sehen können, versuche ich zu bestätigen, wann immer die greaterThan-Funktion true entspricht. Wie Sie in der Ausnahmebedingungsnachricht sehen können, wird diese true durch :param0 ersetzt.

Was läuft also falsch im Code?

Antwort

0

Es stellte sich heraus, dass das Problem in der letzten Zeile war. Es muss nicht überprüft werden, ob die Funktion "größer als" gleich "wahr" ist oder nicht.

return cb.equal(cb.greaterThan(subquery, Long.valueOf(1)), true); 

Änderungen

return cb.greaterThan(subquery, Long.valueOf(1)); 

Der Grund, warum ich dieses eine verkorkste ist, weil die Funktion in meiner Anwendung auch eine Variable, die angibt, wann immer oder nicht true oder false hat gesucht. Ich machte eine If-Else-Anweisung, so dass ich cb.greaterThan oder cb.lessThanOrEqualTo abhängig von dieser Variable zurückgeben.

0

Es sieht so aus, als ob Sie keine Unterabfrage benötigen, nur eine GROUP BY - HAVING - Anweisung wie folgt. Getestet mit EclipseLink:

CriteriaQuery<Tuple> cq = cb.createTupleQuery(); 
Root<Employee> root = cq.from(Employee.class); 
Join<Employee, Manager> managers = root.join("managers"); 
Expression<Long> countManagers = cb.count(managers); 
cq.multiselect(root, countManagers); 
cq.groupBy(root); 
cq.having(cb.greaterThan(countManagers, Long.valueOf(1))); 
List<Tuple> result = em.createQuery(cq).getResultList(); 
for (Tuple t : result) { 
    Employee emp = (Employee) t.get(0); 
} 
+0

Vielen Dank für Ihre Antwort. Ich bin jedoch nicht in der Lage, ein Prädikat zu erstellen, das wahr oder falsch zurückgibt, wenn die Anzahl größer als 1 ist oder nicht. Wie in der Frage definiert, scheint meine SQL-Abfrage korrekt zu sein. – Joetjah

+0

Es ist schwierig zu sagen, ob Ihre Abfrage korrekt ist oder nicht, da sie die Ausnahme auslöst. Und die Kriterien-API javadoc ist ziemlich vage über die korrekte Verwendung von Unterabfragen. Ich schlage vor, dass Sie damit beginnen, dass etwas funktioniert, und meine Lösung funktioniert tatsächlich und erzeugt eine SQL-Abfrage, die genau das tut, was Sie brauchen. – perissf