2016-05-21 6 views
1

Ich bin neu in JPA Criteria API.JPA-Kriterien API NICHT in Code-Vereinfachung und Optimierung

2 Fragen:

  1. Wie kann ich diese Methode, benötigt Parameter gibt die Klasse sowohl 3. und 4. Aussagen weiter vereinfachen?
  2. Wie kann ich die Operation NOT IN in NOT EXISTS übersetzen, um die Leistung zu verbessern?

    public List<Pilot> getPilotsExcept(final Integer... entityIds) { 
    
        final CriteriaBuilder critBuilder = em.getCriteriaBuilder(); 
    
        final CriteriaQuery<Pilot> critQuery = 
         critBuilder.createQuery(getEntityClass()); 
    
        final Root<Pilot> root = critQuery.from(getEntityClass()); // Why pass the class again? 
    critQuery.select(root).where(
        critBuilder.not(root.get("id").in(Arrays.asList(entityIds)))); 
    
        final TypedQuery<Pilot> typedQuery = em.createQuery(critQuery); 
        return typedQuery.getResultList(); 
    } 
    
+0

Vielleicht Duplikat mit http://stackoverflow.com/questions/13859780/building-a-query-using-not -exists-in-jpa-Kriterien-api – Moolerian

Antwort

1

Warum wieder die Klasse übergeben?

In Kriterien API-Abfrage Komponenten werden durch Objekte dargestellt. So select Klausel und die from Klausel durch Objekte dargestellt:

  • Die select Klausel wird wie folgt dargestellt:

    CriteriaQuery<Pilot> critQuery = critBuilder.createQuery(getEntityClass()); 
    

    Die Pilot Klasse in der obigen Linie stellt den Rückgabetyp des Abfrageergebnisses.

  • Und auf der anderen Seite der from-Klausel der Abfrage wie folgt definiert ist:

    final Root<Pilot> root = critQuery.from(getEntityClass()); 
    

In diesem Beispiel sowohl die Root und CriteriaQuery zufällig den gleichen Typen. Dies gilt jedoch nicht für alle Abfragen. In einigen Abfragen möchten Sie möglicherweise ein oder mehrere Attribute aus der Abfrage zurückgeben (aber nicht alle Attribute der Entitäten, die an einer Abfrage beteiligt sind). In diesen Fällen unterscheidet sich der Typ, den Sie in CriteriaQuery angeben, von dem Typ, den Sie in Root verwenden. Angenommen, Sie haben ein name Attribut in Ihrer Pilot Entität und Sie sind nur an der Liste der Namen der Pilot Entitäten interessiert.

CrtieriaQuery<String> cq = cb.createQuery(String.class); 

Aber die Definition der Root nicht ändert, in Ihrem Beispiel: In diesem Fall Ihre CriteriaQuery werden wie folgt definiert werden.

NICHT VORHANDEN Ausdruck

Lage sein, Ihre not in expresion zu not exists Form konvertieren Sie eine Unterabfrage mit dem IDs zu formulieren haben. Hier ein Auszug aus der JPA-Spezifikation:

Ein EXISTS-Ausdruck ist ein Prädikat, das nur dann wahr ist, wenn das Ergebnis der Unterabfrage aus einem oder mehreren Werten besteht und andernfalls falsch ist. Die Syntax eines existiert Ausdruck

exists_expression :: = [NOT] EXISTS (Unterabfrage) Natürlich muss dies auf die Kriterien API übersetzt werden, wobei in diesem Fall die Syntax

wird nicht (existiert (Unterabfrage)). Hier

ist ein Beispiel für eine Unterabfrage zu schaffen (Pseudocode):

Subquery<Integer> sq = critQuery.subquery(Integer.class); 
Root<Pilot> pilot = sq.from(Pilot.class); 
sq.select(pilot.<Integer>get("id")); 
sq.where(<some_condition>); 
+0

Sie haben beide Punkte sehr gut erklärt. Ich habe bemerkt, dass der Code alles während des Tests löscht und ich konnte es korrigieren. Ich bin jetzt zuversichtlich, dass ich den Code basierend auf Ihrer Erklärung in "nicht vorhanden" übersetzen kann. Danke für die umfassende Antwort. –