Comment créer une requête Distinct dans HQL
Question
Existe-t-il un moyen de créer une requête Distinct dans HQL. Soit en utilisant le code "distinct". mot-clé ou une autre méthode. Je ne sais pas si distinct est un travail de clé valide pour HQL, mais je recherche l’équivalent HQL du mot clé SQL "distinct".
La solution
Voici un extrait de code HTML 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});
Autres conseils
Il convient de noter que le mot clé distinct
dans HQL ne correspond pas directement au mot clé distinct
dans SQL.
Si vous utilisez le mot clé distinct
dans HQL, Hibernate utilisera parfois le mot clé SQL distinct
, 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
Dans ce cas, il n'est pas possible de filtrer les doublons au niveau SQL. Hibernate utilise donc un ResultTransformer
pour filtrer les doublons après l'exécution de la requête SQL.
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 avec les requêtes HQL. Quand j'ai essayé
final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);
cela n'a pas fonctionné. Je devais transformer manuellement comme ça:
final List found = trans.transformList(qry.list());
Avec l’API Criteria, les transformateurs fonctionnaient parfaitement.
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 "distinct". résultats. 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 obtenu le code "distinct". retour je voulais. Un exemple serait au lieu de voir 00 quatre fois je viens de le voir une 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 vous a aidé! Encore une fois, cela ne fonctionnera que si vous suivez les pratiques de codage qui implémentent le type de projet service, dao et modèle.
Supposons qu'une entité cliente soit mappée sur la table CUSTOMER_INFORMATION et que vous souhaitez obtenir la liste des prénoms distincts du client. Vous pouvez utiliser l'extrait ci-dessous pour obtenir le même.
Query distinctFirstName = session.createQuery("select ci.firstName from Customer ci group by ci.firstName");
Object [] firstNamesRows = distinctFirstName.list();
J'espère que ça aide. Nous utilisons donc ici group by au lieu d'utiliser un mot clé distinct.
De même, j’ai trouvé difficile d’utiliser un mot clé distinct lorsque je souhaite l’appliquer à plusieurs colonnes. Par exemple, je veux obtenir une liste distincte de firstName, lastName puis group by fonctionnerait tout simplement. J'ai eu du mal à utiliser distinct dans ce cas.
Vous pouvez utiliser le même mot-clé dans votre générateur de critères, comme ceci.
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.
J'ai reçu une réponse permettant à Hibernate Query Language d'utiliser des champs distincts. Vous pouvez utiliser * SELECT DISTINCT (TO_CITY) FROM FLIGHT_ROUTE *. Si vous utilisez la requête SQL , elle renvoie la liste des chaînes. Vous ne pouvez pas utiliser la valeur renvoyée par classe d'entité. La solution pour résoudre ce type de problème consiste donc à 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 reçu DISTINCT ROUTE_ID et entré sous forme de liste. Et la requête IN filtre le TO_CITY distinct de IN (Liste).
Le type de retour est le type de bean Entity. Donc, vous pouvez le faire en AJAX tel que AutoComplement .
Peut-être que tout soit OK