J'ai une Order
classe qui a une liste de OrderTransactions
et je l'ai mappée avec un mappage Hibernate un-à-plusieurs comme ceci:
@OneToMany(targetEntity = OrderTransaction.class, cascade = CascadeType.ALL)
public List<OrderTransaction> getOrderTransactions() {
return orderTransactions;
}
Ces derniers Order
ont également un champ orderStatus
, qui est utilisé pour le filtrage avec les critères suivants:
public List<Order> getOrderForProduct(OrderFilter orderFilter) {
Criteria criteria = getHibernateSession()
.createCriteria(Order.class)
.add(Restrictions.in("orderStatus", orderFilter.getStatusesToShow()));
return criteria.list();
}
Cela fonctionne et le résultat est comme prévu.
Voici maintenant ma question : pourquoi, lorsque je définis explicitement le type de récupération sur EAGER
, les Order
s apparaissent-ils plusieurs fois dans la liste résultante?
@OneToMany(targetEntity = OrderTransaction.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public List<OrderTransaction> getOrderTransactions() {
return orderTransactions;
}
Comment devrais-je changer mon code de critère pour atteindre le même résultat avec le nouveau paramètre?
Réponses:
C'est en fait le comportement attendu si j'ai bien compris votre configuration.
Vous obtenez la même
Order
instance dans n'importe lequel des résultats, mais puisque maintenant vous effectuez une jointure avec leOrderTransaction
, il doit renvoyer le même nombre de résultats qu'une jointure SQL régulière retourneraDonc en fait, il devrait apparaître plusieurs fois. ceci est très bien expliqué par l'auteur (Gavin King) lui-même ici : cela explique à la fois pourquoi et comment obtenir encore des résultats distincts
Également mentionné dans la FAQ Hibernate :
la source
En plus de ce qui est mentionné par Eran, un autre moyen d'obtenir le comportement souhaité est de définir le transformateur de résultat:
la source
essayer
par exemple
}
la source
N'utilisez pas List et ArrayList mais Set et HashSet.
la source
En utilisant Java 8 et Streams, j'ajoute dans ma méthode utilitaire cette déclaration de retour:
Les flux suppriment les doublons très rapidement. J'utilise l'annotation dans ma classe Entity comme ceci:
Je pense qu'il est bether dans mon application d'utiliser la session dans la méthode où j'ai besoin de données de la base de données. Closse session quand j'ai fait. Bien sûr, configurer ma classe Entity pour utiliser le type de récupération leasy. Je vais refactoriser.
la source
J'ai le même problème pour récupérer 2 collections associées: l'utilisateur a 2 rôles (Set) et 2 repas (List) et les repas sont dupliqués.
DISTINCT n'aide pas (requête DATA-JPA):
Enfin j'ai trouvé 2 solutions:
Solution finale:
la source
Au lieu d'utiliser des hacks comme:
Set
au lieu deList
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
qui ne modifient pas votre requête SQL, nous pouvons utiliser (en citant les spécifications JPA)
qui modifie la requête SQL résultante, ayant ainsi un
DISTINCT
.la source
Cela ne semble pas un bon comportement d'appliquer une jointure externe et d'apporter des résultats dupliqués. La seule solution qui reste est de filtrer notre résultat à l'aide de flux. Merci java8 qui donne un moyen plus simple de filtrer.
la source