web-dev-qa-db-fra.com

Comment créer une requête Distinct dans HQL

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".

94
Mike Pone

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});
121
Feet

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.

51
Daniel Alexiuc

faire quelque chose comme ça la prochaine fois 

 Criteria crit = (Criteria) session.
                  createCriteria(SomeClass.class).
                  setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

 List claz = crit.list();
15
Michael

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();
9
aadi53

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.

4
Tadeusz Kopec

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.

3
Nathan Mitchell

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.

2
chammu

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.

1
Santosh Singh

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

0
San Lin Naing