Les Projections.count() et des Projections.countDistinct() fois de suite dans la même requête
EDIT: j'ai édité ce post complètement, de sorte que la nouvelle description de mon problème comprend tous les détails et pas seulement ce que j'ai déjà considérés comme pertinents. Peut-être que cette nouvelle description pour aider à résoudre le problème, je suis confronté à.
J'ai deux classes d'entité, de la Clientèle et CustomerGroup. La relation entre les clients et groupes de clients est ManyToMany. Les groupes de clients sont annotés de la manière suivante dans la classe de la Clientèle.
@Entity
public class Customer {
...
@ManyToMany(mappedBy = "customers", fetch = FetchType.LAZY)
public Set<CustomerGroup> getCustomerGroups() {
...
}
...
public String getUuid() {
return uuid;
}
...
}
Le client de référence dans les groupes de clients de la classe est annotée de la façon suivante
@Entity
public class CustomerGroup {
...
@ManyToMany
public Set<Customer> getCustomers() {
...
}
...
public String getUuid() {
return uuid;
}
...
}
Il est à noter que la CustomerGroup et les catégories de Clients ont également un UUID champ. L'UUID est une chaîne unique (unicité n'est pas forcé dans le modèle de données, comme vous pouvez le voir, il est traité comme tout autre normal de la chaîne).
Ce que je suis en train de faire, est de récupérer tous les clients qui n'appartiennent à aucun groupe de clients OU le client est un groupe "groupe valide". La validité d'un groupe de clients est défini par une liste de validité des Uuid.
J'ai créé les critères suivants requête
Criteria criteria = getSession().createCriteria(Customer.class);
criteria.setProjection(Projections.countDistinct("uuid"));
criteria = criteria.createCriteria("customerGroups", "groups", Criteria.LEFT_JOIN);
List<String> uuids = getValidUUIDs();
Criterion criterion = Restrictions.isNull("groups.uuid");
if (uuids != null && uuids.size() > 0) {
criterion = Restrictions.or(criterion, Restrictions.in(
"groups.uuid", uuids));
}
criteria.add(criterion);
Lors de l'exécution de la requête, la requête SQL suivante
select
count(*) as y0_
from
Customer this_
left outer join
CustomerGroup_Customer customergr3_
on this_.id=customergr3_.customers_id
left outer join
CustomerGroup groups1_
on customergr3_.customerGroups_id=groups1_.id
where
groups1_.uuid is null
or groups1_.uuid in (
?, ?
)
La requête est exactement ce que je voulais, mais avec une exception. Depuis un Client peut appartenir à plusieurs CustomerGroups, à gauche rejoindre la CustomerGroup résultat sera dupliqué objets de Client. D'où la count(*)
donnera une valeur fausse, car elle ne prend en compte que le nombre de résultats. J'ai besoin d'obtenir le montant de unique clients et ce, je m'attendais à atteindre à l'aide de la Projections.countDistinct("uuid");
-projection. Pour une raison quelconque, comme vous pouvez le voir, la projection sera toujours un count(*)
requête à la place de l' count(distinct uuid)
. Remplacement de la projection countDistinct
avec juste count("uuid")
résultat sera exactement le même requête.
Je fais quelque chose de mal ou est-ce un bug?
===
"Problème" résolu. Raison: PEBKAC (Problème Existe Entre le Clavier Et la Chaise). J'ai eu une branche dans mon code et je ne savais pas que la branche a été exécuté. Cette branche utilisée rowCount() au lieu de countDistinct().
J'ai édité la question pour contenir tout le code lié à mon problème.
Pour d'autres, aux prises avec le même problème, reportez-vous à cette question: stackoverflow.com/questions/4616607/...
OriginalL'auteur Kim L | 2010-02-23
Vous devez vous connecter pour publier un commentaire.
Thre est bug dans 3.5.1
Après
cr.setProjection(Projections.countDistinct("memberId"));
SQL résultat est le comte(memberId)
bo pas count(distinct memberId)
après de débogage ....
distinct est remarqué, mais pas utilisé.
et ... dans AggregateProjection
seulement getFunctionName() = nomfonction = "count" est utilisé !!!
public class AggregateProjection s'étend SimpleProjection {
OriginalL'auteur OxUlsen
"Problème" résolu. Raison: PEBKAC (Problème Existe Entre le Clavier Et la Chaise). J'ai eu une branche dans mon code et je ne savais pas que la branche a été exécuté. Cette branche utilisée rowCount() au lieu de countDistinct().
OriginalL'auteur Kim L
essayer de débogage de la méthode toSqlString dans la classe CountProjection. En regardant le code, je ne peut que l'image que distincte n'était pas vrai; je ne vois pas d'autre raison pourquoi le distinct ne serait pas inclus:
ce qui concerne,
Stijn
OriginalL'auteur Stijn Geukens
Je suppose que c'est parce que votre champ 'id' est un domaine unique, et hibernate sait que.
La requête de donner un résultat différent lorsque vous utilisez 'distinct'?
OriginalL'auteur Fortega
Peut-être que le champ ID est défini comme unique, de toute façon? Essayez d'utiliser un autre champ, qui n'est pas unique.
OriginalL'auteur Thomas Lötzer