Réponses:
Voici un extrait de hql que nous utilisons. (Les noms ont été modifiés pour protéger les identités)
String queryString = "select distinct f from Foo f inner join foo.bars as b" +
" where f.creationDate >= ? and f.creationDate < ? and b.bar = ?";
return getHibernateTemplate().find(queryString, new Object[] {startDate, endDate, bar});
Il est à noter que le distinct
mot - clé en HQL ne correspond pas directement au distinct
mot - clé en SQL.
Si vous utilisez le distinct
mot - clé dans HQL, alors Hibernate utilisera parfois le distinct
mot-clé SQL, mais dans certaines situations, il utilisera un transformateur de résultat pour produire des résultats distincts. Par exemple, lorsque vous utilisez une jointure externe comme celle-ci:
select distinct o from Order o left join fetch o.lineItems
Il n'est pas possible de filtrer les doublons au niveau SQL dans ce cas, donc Hibernate utilise a ResultTransformer
pour filtrer les doublons une fois la requête SQL effectuée.
faire quelque chose comme ça la prochaine fois
Criteria crit = (Criteria) session.
createCriteria(SomeClass.class).
setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
List claz = crit.list();
Vous pouvez également utiliser Criteria.DISTINCT_ROOT_ENTITY
avec la requête Hibernate HQL.
Exemple:
Query query = getSession().createQuery("from java_pojo_name");
query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return query.list();
J'ai eu quelques problèmes avec les transformateurs de résultats combinés aux requêtes HQL. Quand j'ai essayé
final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);
ça n'a pas marché. J'ai dû transformer manuellement comme ceci:
final List found = trans.transformList(qry.list());
Avec Criteria, les transformateurs fonctionnaient très bien.
Ma requête principale ressemblait à ceci dans le modèle:
@NamedQuery(name = "getAllCentralFinancialAgencyAccountCd",
query = "select distinct i from CentralFinancialAgencyAccountCd i")
Et je n'obtenais toujours pas ce que je considérais comme des résultats «distincts». Ils étaient simplement distincts en fonction d'une combinaison de clés primaires sur la table.
Ainsi , dans le DaoImpl
j'ai ajouté un changement d' une ligne et a fini par obtenir le retour , je voulais « distinct ». Un exemple serait au lieu de voir 00 quatre fois, je le vois maintenant une seule fois. Voici le code que j'ai ajouté au DaoImpl
:
@SuppressWarnings("unchecked")
public List<CacheModelBase> getAllCodes() {
Session session = (Session) entityManager.getDelegate();
org.hibernate.Query q = session.getNamedQuery("getAllCentralFinancialAgencyAccountCd");
q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); // This is the one line I had to add to make it do a more distinct query.
List<CacheModelBase> codes;
codes = q.list();
return codes;
}
J'espère que cela a aidé! Encore une fois, cela peut ne fonctionner que si vous suivez des pratiques de codage qui implémentent le type de projet service, DAO et modèle.
Supposons que vous ayez une entité client mappée à la table CUSTOMER_INFORMATION et que vous souhaitiez obtenir la liste des prénoms distincts du client. Vous pouvez utiliser l'extrait ci-dessous pour obtenir la même chose.
Query distinctFirstName = session.createQuery("select ci.firstName from Customer ci group by ci.firstName");
Object [] firstNamesRows = distinctFirstName.list();
J'espère que cela aide. Nous utilisons donc ici group by au lieu d'utiliser un mot-clé distinct.
Aussi, auparavant, j'ai trouvé difficile d'utiliser un mot-clé distinct lorsque je veux l'appliquer à plusieurs colonnes. Par exemple, je veux obtenir une liste de firstName distincts, lastName puis group by fonctionnerait simplement. J'ai eu du mal à utiliser distinct dans ce cas.
J'ai une réponse pour Hibernate Query Language pour utiliser des champs distincts. Vous pouvez utiliser * SELECT DISTINCT (TO_CITY) FROM FLIGHT_ROUTE *. Si vous utilisez une requête SQL , elle renvoie une liste de chaînes. Vous ne pouvez pas l'utiliser comme valeur de retour par classe d'entité. La réponse pour résoudre ce type de problème est donc d'utiliser HQL avec SQL .
FROM FLIGHT_ROUTE F WHERE F.ROUTE_ID IN (SELECT SF.ROUTE_ID FROM FLIGHT_ROUTE SF GROUP BY SF.TO_CITY);
À partir de l' instruction de requête SQL , il a obtenu DISTINCT ROUTE_ID et entré sous forme de liste. Et la requête IN filtre la TO_CITY distincte de IN (List).
Le type de retour est le type Entity Bean. Vous pouvez donc le faire dans AJAX, comme le complément automatique .
Que tout va bien
Vous pouvez vous le mot-clé distinct dans votre générateur de critères comme celui-ci.
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Orders> query = builder.createQuery(Orders.class);
Root<Orders> root = query.from(Orders.class);
query.distinct(true).multiselect(root.get("cust_email").as(String.class));
Et créez le constructeur de champ dans votre classe de modèle.
Si vous avez besoin d'utiliser un nouveau mot-clé pour un DTO personnalisé dans votre instruction select et que vous avez besoin d' éléments distincts , utilisez new en dehors de new comme suit:
select distinct new com.org.AssetDTO(a.id, a.address, a.status) from Asset as a where ...