Risposte:
Ecco uno snippet di hql che usiamo. (I nomi sono stati modificati per proteggere le identità)
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});
Vale la pena notare che la distinct
parola chiave in HQL non si associa direttamente alla distinct
parola chiave in SQL.
Se si utilizza la distinct
parola chiave in HQL, a volte Hibernate utilizzerà la distinct
parola chiave SQL, ma in alcune situazioni utilizzerà un trasformatore di risultati per produrre risultati distinti. Ad esempio, quando utilizzi un outer join come questo:
select distinct o from Order o left join fetch o.lineItems
In questo caso non è possibile filtrare i duplicati a livello SQL, quindi Hibernate utilizza a ResultTransformer
per filtrare i duplicati dopo che è stata eseguita la query SQL.
fai qualcosa di simile la prossima volta
Criteria crit = (Criteria) session.
createCriteria(SomeClass.class).
setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
List claz = crit.list();
Puoi anche usarlo Criteria.DISTINCT_ROOT_ENTITY
con la query Hibernate HQL.
Esempio:
Query query = getSession().createQuery("from java_pojo_name");
query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return query.list();
Ho avuto alcuni problemi con i trasformatori di risultati combinati con le query HQL. Quando ho provato
final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);
non ha funzionato. Ho dovuto trasformare manualmente in questo modo:
final List found = trans.transformList(qry.list());
Con Criteria API i trasformatori hanno funzionato perfettamente.
La mia domanda principale era simile a questa nel modello:
@NamedQuery(name = "getAllCentralFinancialAgencyAccountCd",
query = "select distinct i from CentralFinancialAgencyAccountCd i")
E non stavo ancora ottenendo quelli che consideravo risultati "distinti". Erano solo distinti in base a una combinazione di chiavi primarie sul tavolo.
Così nel DaoImpl
ho aggiunto un cambio di riga e ho finito per ottenere il ritorno "distinto" che volevo. Un esempio sarebbe invece di vedere 00 quattro volte, ora lo vedo solo una volta. Ecco il codice che ho aggiunto a 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;
}
Spero che questo abbia aiutato! Ancora una volta, questo potrebbe funzionare solo se stai seguendo le pratiche di codifica che implementano il servizio, il dao e il tipo di modello del progetto.
Supponiamo di avere un'entità cliente mappata alla tabella CUSTOMER_INFORMATION e di voler ottenere un elenco di firstName distinti del cliente. Puoi utilizzare lo snippet di seguito per ottenere lo stesso.
Query distinctFirstName = session.createQuery("select ci.firstName from Customer ci group by ci.firstName");
Object [] firstNamesRows = distinctFirstName.list();
Spero possa essere d'aiuto. Quindi qui stiamo usando il gruppo invece di usare una parola chiave distinta.
Inoltre in precedenza ho trovato difficile utilizzare una parola chiave distinta quando voglio applicarla a più colonne. Ad esempio, voglio ottenere un elenco di firstName distinti, lastName quindi group by funzionerebbe semplicemente. In questo caso ho avuto difficoltà a usare distinti.
Ho una risposta per Hibernate Query Language per utilizzare i campi distinti. Puoi utilizzare * SELECT DISTINCT (TO_CITY) FROM FLIGHT_ROUTE *. Se usi la query SQL , restituisce String List. Non puoi usarlo come valore di ritorno per Entity Class. Quindi la risposta per risolvere quel tipo di problema è usare HQL con SQL .
FROM FLIGHT_ROUTE F WHERE F.ROUTE_ID IN (SELECT SF.ROUTE_ID FROM FLIGHT_ROUTE SF GROUP BY SF.TO_CITY);
Da SQL un'istruzione di interrogazione ha ottenuto route_id DISTINCT e l'ingresso in una lista. E la query IN filtra il distinto TO_CITY da IN (List).
Il tipo restituito è il tipo Entity Bean. Quindi puoi farlo in AJAX come AutoComplement .
Che tutto vada bene
Puoi tu la parola chiave distinta nel tuo generatore di criteri come questo.
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));
E crea il costruttore del campo nella tua classe del modello.
Se è necessario utilizzare una nuova parola chiave per un DTO personalizzato nell'istruzione select e sono necessari elementi distinti , utilizzare nuovo al di fuori di nuovo come segue:
select distinct new com.org.AssetDTO(a.id, a.address, a.status) from Asset as a where ...