Est-il possible de créer une requête Distinct dans HQL? Soit en utilisant le mot clé "distinct" ou une autre méthode. Je ne suis pas sûr que le mot clé distinct soit valide pour HQL, mais je recherche l'équivalent HQL du mot clé SQL "distinct".
Voici un extrait de HQL que nous utilisons. (Les noms ont été changé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 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 une variable ResultTransformer
pour filtrer les doublons après la requête SQL a été 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 avec des requêtes HQL. Quand j'ai essayé
final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);
ça n'a pas marché. Je devais transformer manuellement comme ça:
final List found = trans.transformList(qry.list());
Avec les critères de 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 des résultats "distincts". Ils étaient simplement distincts en fonction d'une combinaison de clés primaires sur la table.
Donc, dans la DaoImpl
, j'ai ajouté un changement d'une ligne et j'ai fini par obtenir le retour "distinct" que 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é à la 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 ne fonctionne que si vous suivez les pratiques de codage qui implémentent le type de projet service, dao et modèle.
Supposons que vous avez une entité client 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 plus, j'avais déjà eu du mal à utiliser un mot clé distinct lorsque je voulais 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 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.
J'ai une réponse pour Hibernate Query Language qui utilise des champs distincts . Vous pouvez utiliser * SELECT DISTINCT (TO_CITY) DE FLIGHT_ROUTE * . Si vous utilisezSQLquery, il renvoie la liste de 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 à utiliserHQLavecSQL.
FROM FLIGHT_ROUTE F WHERE F.ROUTE_ID IN (SELECT SF.ROUTE_ID FROM FLIGHT_ROUTE SF GROUP BY SF.TO_CITY);
DeSQLinstruction de requête, elle obtient DISTINCT ROUTE_ID et une entrée sous forme de liste . Et une requête IN filtre le TO_CITY distinct de IN (Liste).
Le type de retour est de type Entity Bean . Vous pouvez donc le sélectionner dans AJAX tel que AutoComplement .
Que tout soit ok