Domanda

Supponendo che ho classi utente e UserGroup. C'è un opzionale 1-molti gruppi di associazione utente e l'associazione viene mappato da entrambi i lati (il lato UserGroup tramite una proprietà denominata "membri", che è un HashSet, lato utente tramite proprietà "gruppo").

Utilizzando l'API criteri, come posso query per tutti i gruppi, ordinati per numero di membri del gruppo?

(Modifica) avrei dovuto notare quando ho chiesto questo che l'impaginazione veniva eseguita in SQL, quindi l'ordinamento deve essere eseguita anche in SQL, se possibile.

È stato utile?

Soluzione

Un'altra opzione sarebbe quella di utilizzare l'annotazione @formula che è fondamentalmente l'equivalente di creazione di una SELECT nidificato in modo da poter ottenere presso la conta.

Sul vostro DB oggetti Property / membro in questione (che si dovrebbe creare), aggiungere l'annotazione per il getter come:

@formula ( "(SELECT COUNT (TABLE_NAME.ID) vedi tabella dove qualunque cosa ...)") lungo getNewProperty pubblico {    tornare newProperty; }

Poi indirizzare il membro direttamente per entrare in possesso dei vostri valori di conteggio ...

Nota: Tenere presente che quando si specifica sql entro l'annotazione formula, è necessario specificare i nomi dei campi direttamente quando si fa riferimento alla tabella oggetti corrente (questo) come offerte Hibernate con questo si. Quindi nel tuo clausola WHERE basta usare ID o qualsiasi altra cosa sul proprio quando si fa riferimento alla tabella oggetti corrente che ho il sospetto è UserGroup.

ho dovuto avere un setter per la mia nuova proprietà al fine di Hibernate al lavoro e impedire al compilatore di lamentarsi.

Ci possono essere altri modi intelligenti di utilizzo @formula, ma io sono abbastanza nuovo a questo e non ci non sembra essere molto molta documentazione su questo argomento ...

Se non hai mai usato nidificato seleziona Prima, potrebbe essere un'idea per di ricreare solo in SQL prima -. Che mi ha aiutato

Spero che questo aiuti

Altri suggerimenti

Non è possibile di default utilizzando Citeria API, ma è possibile estendere classe org.hibernate.criterion.Order. Questo articolo è su come estendere tale classe: http://blog.tremend.ro/2008/06/10/how-to-order-by-a-custom-sql-formulaexpression-when-using-hibernate -Criteri-api

Il mio sollution è:

public class SizeOrder extends Order {

    protected String propertyName;
    protected boolean ascending;

    protected SizeOrder(String propertyName, boolean ascending) {
        super(propertyName, ascending);
        this.propertyName = propertyName;
        this.ascending = ascending;
    }

    public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
        String role = criteriaQuery.getEntityName(criteria, propertyName) + '.' + criteriaQuery.getPropertyName(propertyName);
        QueryableCollection cp = (QueryableCollection) criteriaQuery.getFactory().getCollectionPersister(role);

        String[] fk = cp.getKeyColumnNames();
        String[] pk = ((Loadable) cp.getOwnerEntityPersister())
                .getIdentifierColumnNames();
        return " (select count(*) from " + cp.getTableName() + " where "
                + new ConditionFragment()
                        .setTableAlias(
                                criteriaQuery.getSQLAlias(criteria, propertyName)
                        ).setCondition(pk, fk)
                    .toFragmentString() + ") "
                + (ascending ? "asc" : "desc");
    }

    public static SizeOrder asc(String propertyName) {
        return new SizeOrder(propertyName, true);
    }
    public static SizeOrder desc(String propertyName) {
        return new SizeOrder(propertyName, false);
    }
}

Il metodo si basa su toSqlString classe org.hibernate.criterion.SizeExpression. (Fonte: http://javasourcecode.org/html/open-source/hibernate/hibernate-3.6.0.Final/org/hibernate/criterion/SizeExpression.java.html )

Esempio di utilizzo:

hibernateSession.createCriteria(UserGroup.class).addOrder( SizeOrder.asc("members") ).list();

Questa lista gruppi di utenti ordinate dalla dimensione dei membri ascendente, in cui "membri" è la raccolta utente in entità UserGroup.

Si potrebbe probabilmente così questa definendo una "proprietà derivata" sul soggetto, che sarebbe una proprietà di sola lettura che restituisce la dimensione della collezione all'interno di tale entità. Il modo più semplice per definire una proprietà derivata è documentato qui :

  

update, insert (opzionale - il default   vero): specifica che il mappato   colonne devono essere inclusi in SQL   UPDATE e / o inserire dichiarazioni.   Impostare entrambe a false consente una pura   "Derivata" proprietà il cui valore è   inizializzato da qualche altra proprietà   che associa alla stessa colonna (s), o   un trigger o un'altra applicazione.

Una volta che la proprietà è definita, si dovrebbe essere in grado di utilizzare il nome della proprietà come una clausola di ordine nella API criteri, proprio come qualsiasi altra proprietà. Non ho provato io stesso, però.

Se funziona, sarà probabilmente essere fatto come quelli in memoria, dal momento che non sarà in grado di mappare a SQL. Se questo è un problema, allora lo stesso link qui sopra documenti come implementare una proprietà derivata utilizzando un frammento SQL personalizzata:

  

Una caratteristica potente è derivato   proprietà. Queste proprietà sono da   Definizione di sola lettura. La proprietà   valore viene calcolato al momento del caricamento. voi   dichiarare il calcolo come SQL   espressione. Questo si traduce poi in un   SELEZIONA subquery clausola del SQL   query che carica un esempio:

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top