2017-07-26 2 views
0

sagen, dass ich zumindest diese beiden Entitäten:Hibernate Kriterien, verschiedene Beziehungseigenschaft

class Person { 
    String firstname, lastname; 

    Address address; 

    ManyOtherPropertiesAndEntities ...; 
} 

class Address { 
     String street; 
     Country country; 
} 

Nun würde Ich mag die Person Tabelle abzufragen und NUR Personen, die auf verschiedenen Straßen leben.

Das heißt, ignorieren alle Personen, die auf derselben Straße leben, und nur eine dieser Person zurückkehren, irgendeine.

Wie kann ich eine solche Abfrage durchführen?

Verwenden Sie möglicherweise Kriterien?

Criteria criteria = session.createCriteria(Person.class, "person"); 

Criteria addressCriteria = criteria.createCriteria("address") 

criteria.setProjection(
        Projections.distinct(
         Projections.projectionList().add(Projections.property("address.street")) 
        ) 
      ); 

Dies funktioniert nicht wirklich.

Ich habe auch versucht zu tun:

projectionList.add(Projections.sqlProjection("DISTINCT ON (address.street), ... ", columns.toArray(new String[columns.size()]), types.toArray(new Type[types.size()]))); 

Aber auch fruchtlos.

>>>>>>>>>>>>>>>>>>>>>>> EDIT < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

Ich konnte dies erreichen zu laufen und generieren eine SQL-Abfrage, die tatsächlich Ergebnisse in einer reinen SQL-Modus zurückkehrt, scheint aber null in Hibernate zurück:

List<String> columns = Lists.lst(); 
             List<Type> types  = Lists.lst(); 

             bondCriteria.setProjection(
               Projections.sqlProjection ("DISTINCT ON (tvmux2_.polarization) * " 
                 , columns.toArray (new String[columns.size()]) 
                 , types.toArray (new Type[types.size()]) 
               ) 

               // Projections.projectionList().add(Projections.distinct(Projections.property("polarization"))) 
             ); 

             ResultTransformer resultTransformer = new ResultTransformer() { 
               @Override 
               public List transformList(List collection) { 
                 return null; 
               } 

               @Override 
               public Object transformTuple(Object[] tuple, String[] aliases) { 
                 return null; 
               } 
             }; 

             bondCriteria.setResultTransformer(resultTransformer); 

* ITS 2017 und SO noch hat keinen geeigneten Editor, um Code einfach formatieren zu können, so dass Einrückung und Kopieren und Einfügen keine komplette Hölle ist. Fühlen Sie sich frei, horizontal zu scrollen. *

Dies erzeugt Teh folgende Abfrage im Grunde

select DISTINCT ON (tvmux2_.polarization) * from TvChannelBond this_ inner join TvChannel tvchannel1_ on this_.channel=tvchannel1_.id inner join TvMux tvmux2_ on this_.mux=tvmux2_.id where this_.enabled=true order by tvmux2_.polarization asc limit 100 

die Ergebnisse in einem nicht den Ruhezustand zurückkehrt.

Da jedoch sqlProjection-Methode die Ergänzung von 3 Params erfordert, bin ich nicht sicher, was Sie zu den zweiten und dritten Params hinzufügen. Typen können nicht anders als vordefinierte Hibernate-Typen wie DOUBLE, STRING usw. sein.

Wenn Debuggen in die resultTransformer, wird es in transformTuple mit der Länge Null Tupel [] und Aliase [].

Könnte mit der sqlProjection Länge Null Typen und Spalten Listen zu tun haben.

+0

Nur eine Frage: Warum würden Sie überhaupt die Hibernate-Kriterien verwenden? Es ist veraltet und wird nicht unterstützt. BTW, für diese Art von Anforderung, würde ich vorschlagen, mit nativer Abfrage zu gehen. – galovics

+0

@galovics Es ist bereits eine große Kriterienabfrage vorhanden. Dies ist nur eine Addon-Option, und ich möchte vermeiden, den gesamten Abfrage-Generator für diesen Fall neu schreiben zu müssen. Kriterienabfragen veraltet? Was wird jetzt vorgeschlagen? Sag nicht HQL. – momomo

+0

@galovics Sehen Sie diese https://stackoverflow.com/a/45325401/961018 ... Frage ist jetzt, wie man diese sql Projektion zum hibernate Kriterien dreht. – momomo

Antwort

0

In SQL, können Sie es wie folgt tun:

SELECT p.* 
FROM Address a 
INNER JOIN Person p ON ... 
GROUP BY a.Street 
HAVING p.id = MIN(p.id) 

Diese Anweisung wählt für jedes unterschiedliche Street von Address die Person mit dem minimalen id Wert. Anstelle von MIN(p.id) können Sie natürlich jede andere Feld- und Aggregatfunktion verwenden, die genau einer Person pro Straße entspricht. MAX(p.id) wird funktionieren, MIN(p.lastname) wird nicht, wenn es mehrere "Smith" in einer Straße geben kann.

Können Sie das obige SQL in Ihre Kriterienabfrage umwandeln?

+0

Aktualisiert mit einer Bearbeitung. Basierend auf einer anderen SQL-Abfrage finden Sie hier: https://Stackoverflow.com/a/45325401/961018 Beachten Sie, dass ich weiß, dass die Tabellen und Eigenschaften geändert haben, aber das sollte hier nicht wirklich wichtig sein. – momomo