Question

En supposant que j'ai des classes utilisateur et UserGroup. Il y a un 1-plusieurs en option groupe association d'utilisateurs et l'association est mise en correspondance des deux côtés (le côté UserGroup via une propriété appelée « membres », qui est un HashSet, du côté de l'utilisateur via la propriété « groupe »).

Utilisation de l'API de critères, comment puis-je interroger pour tous les groupes, classés par nombre de membres du groupe?

(Edit) je l'ai dit quand j'ai demandé ce qui était en cours d'exécution en page dans le SQL, de sorte que la commande doit également être effectuée dans le SQL si possible.

Était-ce utile?

La solution

Une autre option serait d'utiliser l'annotation @Formula qui est essentiellement l'équivalent de la création d'une sélection imbriquée afin que vous puissiez accéder à vos comptes.

Sur votre DB objets propriété / membre en question (que vous devez créer), ajouter l'annotation à l'getter comme:

@Formula ( "(SELECT COUNT (TABLE_NAME.ID) DE TABLE OU tout ...)") public long getNewProperty {    retourner newProperty; }

cible ensuite le membre directement à mettre la main sur vos valeurs de comptage ...

Remarque: Sachez que lorsque vous spécifiez le SQL au sein de l'annotation de formule, vous devez spécifier les noms de champs directement lorsque vous faites référence à la table des objets en cours (ce) que des offres mise en veille prolongée avec ce lui-même. Donc, dans votre clause WHERE il suffit d'utiliser ID ou quel que soit son propre lors du référencement de la table des objets en cours que je soupçonne est UserGroup.

Je devais avoir un setter pour ma nouvelle propriété afin de mise en veille prolongée au travail et empêcher le compilateur de se plaindre.

Il peut y avoir d'autres façons intelligentes d'utiliser @Formula, mais je suis tout à fait nouveau à cela et il ne semble pas être une documentation très bien sur le sujet ...

Si vous ne l'avez jamais utilisé CHOISIT imbriqué avant, il pourrait être une idée pour vous recréez juste sql premier -. Qui m'a aidé

Hope this helps

Autres conseils

Il est impossible par défaut en utilisant l'API Citeria mais vous pouvez étendre la classe org.hibernate.criterion.Order. Cet article est sur la façon d'étendre cette classe: http://blog.tremend.ro/2008/06/10/how-to-order-by-a-custom-sql-formulaexpression-when-using-hibernate -Critères-api

Mon sollution est:

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);
    }
}

La méthode est basée sur toSqlString classe org.hibernate.criterion.SizeExpression. (Source: http://javasourcecode.org/html/open-source/hibernate/hibernate-3.6.0.Final/org/hibernate/criterion/SizeExpression.java.html )

Exemple d'utilisation:

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

cette liste de volonté des groupes d'utilisateurs commandés par la taille des membres par ordre croissant, où « membres » est la collection de l'utilisateur dans l'entité UserGroup.

Vous pourriez probablement si cela en définissant une « propriété dérivée » sur votre entité, qui serait une propriété en lecture seule qui retourne la taille de la collection dans cette entité. La meilleure façon de définir une propriété dérivée est documenté ici :

  

update, insert (optionnel - par défaut   true): indique que le tracé   colonnes devraient être inclus dans SQL   UPDATE et / ou instructions INSERT.   Mettre les deux à false permet   propriété « dérivée » dont la valeur est   initialisé par une autre propriété   qui correspond à la même colonne (s), ou par   un déclencheur ou une autre application.

Une fois que la propriété est définie, vous devriez être en mesure d'utiliser le nom de la propriété comme une clause d'ordre dans l'API de critères, comme tout autre bien. Je ne l'ai pas essayé moi-même, cependant.

Si cela fonctionne, il va probablement se faire comme une sorte en mémoire, car il ne sera pas en mesure de mapper à SQL. Si cela est un problème, le même lien ci-dessus documents comment implémenter une propriété dérivée en utilisant un fragment SQL personnalisé:

  

Une fonctionnalité puissante est dérivée   Propriétés. Ces propriétés sont par   lecture seule définition. La propriété   La valeur est calculée au moment du chargement. Toi   déclarer le calcul comme SQL   expression. Cela se traduit alors à un   SELECT clause sous-requête dans le SQL   requête qui charge une instance:

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top