2016-07-05 12 views
1

Ich verwende JPA 2.0 Kriterien Builder. Ich brauche Daten von einer Tabelle und sortiere sie nach Spalten von anderen. Diese Tabellen haben Beziehungen OneToMany:Wie ersetzen Sie native Reihenfolge durch Klausel auf JPA-Äquivalent?

class Club{ 
    @OneToMany(mappedBy = "club") 
    private List<Address> addresses; 
    ... 
    } 

class Address{ 
@JoinColumn(name = "club_id", referencedColumnName = "id") 
@ManyToOne(fetch = FetchType.LAZY) 
private Club club; 

@Column(name = "type") 
private Long type; 

@Column(name = "full_address") 
    private String full_address; 
    ... 
     } 

mehr Adressen von irgendeiner Art sein, aber ich brauche nur eine Zeile dieser spezifischen Adresse.

Ich schreibe native Abfragen mit Unterabfrage, aber es hat ein Problem, weil Unterabfrage nicht in Reihenfolge Klausel und in Select-Klausel in JPA 2.0 verwendet.

select c.full_name from club c 
    ORDER BY (select a.full_address from address a WHERE c.id= a.club_id and a.type=1 LIMIT 1) 


select c.full_name, (select a.full_address from address a WHERE a.type=1 AND c.id=a.club_id LIMIT 1) as full_address FROM club c 
ORDER BY fullAddress; 

Wie kann ich native Reihenfolge durch Klausel auf JPA Äquivalent ersetzen?

Danke!

+0

Gibt es nicht eine Möglichkeit, ein Club in viele Adressen ersetzen und erhält platziert wird die Reihenfolge nicht deterministisch? Anderenfalls kann Ihr JPA-Anbieter Ihnen erlauben, die Unterabfrage in der from-Klausel wie eine Tabelle zu verwenden. Aber es wäre wahrscheinlich besser, wenn Sie die Abfrage modifizieren, um Ihnen das zu geben, was Sie wollen - vermutlich ein eindeutiger vollständiger Name, geordnet nach Adresse. Etwas wie "Wählen Sie c.full_name von Club c verbinden c.addresses a wo a.type = 1 Reihenfolge von a.full_address" – Chris

+0

Vielen Dank für Ihre Antwort. Ein Club kann aus mehreren Adressen mit Typ 1 bestehen. Bei Verwendung von 'join' erscheinen die Dubletten des Clubs. Ich brauche alle Club (falls vorhanden, Adresse mit Typ 1 oder Nein) und sortiere es. – Jun

+0

Fügen Sie ein eindeutiges Schlüsselwort hinzu, aber wenn Typ 1 nicht eindeutig ist, verstehe ich nicht ganz, wie Sie die nicht eindeutigen Adressen auch mit einer Unterabfrage sortieren können. – Chris

Antwort

0

Diese nativen Abfrage löst auch Problem, und es kann von JPA Query

select c.full_name, min(a.full_address) FROM club c LEFT JOIN address a on c.id = a.club_id 
where a.id is null or a.type=1 or not exists(SELECT 1 from address aSub WHERE aSub .club_id=c.id AND aSub.type=1) 
GROUP BY c.id, c.full_name ORDER BY min(a.full_address); 

JPA äquivalent

CriteriaBuilder builder = em.getCriteriaBuilder(); 
     CriteriaQuery<ClubItem> query = builder.createQuery(ClubItem.class); 

    Root<Club> root = query.from(Club.class); 
    Join<Club, Address> addressJoin = root.join(Club_.address, JoinType.LEFT); 

query.select(builder.construct(ClubItem.class, root.get(Club_.id), root.get(Club_.fullName), builder.function("min", String.class, addressJoin.get(Address_.fullAddress)))); 

    Subquery<Address> subquery = query.subquery(Address.class); 
    Root<Address> addressRoot = subquery.from(Address.class); 

    subquery.select(addressRoot); 
    subquery.where(
      builder.and(
        builder.equal(addressRoot.get(Address_.type), 1), 
        builder.equal(addressRoot.get(Address_.clubId), root.get(Club_.id)))); 

    query.where(builder.or(builder.isNull(addressJoin), builder.equal(addressJoin.get(Address_.type), builder.literal(new Long(1))), 
      builder.not(builder.exists(subquery)))); 

    query.groupBy(root.get(Club_.id), root.get(Club_.fullName)) 

      Order order = builder.asc(builder.function("min", String.class, addressJoin.get(Address_.fullAddress))); 

      query.orderBy(order);    

    TypedQuery<ClubItem> contentQuery = em.createQuery(query); 
0

Es ist nicht sehr elegant, aber es wird die ausgeführte Arbeit ...

Stellen Sie Ihre „Club“ Klasse Comparable implementieren. Setze die Reihenfolge-nach-Logik in das Vergleichbare ein. Verwenden Sie dann Collections.sort (unsortedList), um die Liste in sortierter Form zu erhalten. Es gibt auch eine Collections.sort (unsortedList, Comparable) -Methode, die nützlich sein könnte, besonders wenn Sie eine Reihe ähnlicher Methoden verwenden, die sich nur in der Reihenfolge unterscheiden.