Odpowiedzi:
Oto fragment kodu hql, którego używamy. (Nazwy zostały zmienione w celu ochrony tożsamości)
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});
Warto zauważyć, że distinct
słowo kluczowe w HQL nie jest odwzorowywane bezpośrednio na distinct
słowo kluczowe w SQL.
Jeśli użyjesz distinct
słowa kluczowego w HQL, to czasami Hibernate użyje distinct
słowa kluczowego SQL, ale w niektórych sytuacjach użyje transformatora wyników, aby uzyskać różne wyniki. Na przykład, gdy używasz sprzężenia zewnętrznego takiego:
select distinct o from Order o left join fetch o.lineItems
W tym przypadku nie jest możliwe odfiltrowanie duplikatów na poziomie SQL, dlatego Hibernate używa ResultTransformer
do odfiltrowania duplikatów po wykonaniu zapytania SQL.
zrób coś takiego następnym razem
Criteria crit = (Criteria) session.
createCriteria(SomeClass.class).
setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
List claz = crit.list();
Możesz również używać Criteria.DISTINCT_ROOT_ENTITY
z zapytaniem Hibernate HQL.
Przykład:
Query query = getSession().createQuery("from java_pojo_name");
query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return query.list();
Miałem problemy z transformatorami wyników w połączeniu z zapytaniami HQL. Kiedy próbowałem
final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);
to nie zadziałało. Musiałem przekształcić ręcznie w ten sposób:
final List found = trans.transformList(qry.list());
Z Criteria API transformatory działały dobrze.
Moje główne zapytanie wyglądało w modelu tak:
@NamedQuery(name = "getAllCentralFinancialAgencyAccountCd",
query = "select distinct i from CentralFinancialAgencyAccountCd i")
I nadal nie uzyskiwałem tego, co uważałem za „wyraźne” wyniki. Były po prostu różne na podstawie kombinacji klawiszy podstawowych na stole.
Więc DaoImpl
dodałem zmianę o jedną linię i skończyło się na uzyskaniu "wyraźnego" zwrotu, którego chciałem. Przykładem może być to, że zamiast czterokrotnie zobaczyć 00, teraz widzę to tylko raz. Oto kod, który dodałem do 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;
}
Mam nadzieję, że to pomogło! Po raz kolejny może to działać tylko wtedy, gdy przestrzegasz praktyk kodowania, które implementują usługę, dao i model typu projektu.
Załóżmy, że masz jednostkę klienta zmapowaną do tabeli CUSTOMER_INFORMATION i chcesz uzyskać listę odrębnych firstName klienta. Możesz użyć poniższego fragmentu, aby uzyskać to samo.
Query distinctFirstName = session.createQuery("select ci.firstName from Customer ci group by ci.firstName");
Object [] firstNamesRows = distinctFirstName.list();
Mam nadzieję, że to pomoże. Więc tutaj używamy grupy by zamiast używać słowa kluczowego odrębnego.
Również wcześniej było mi trudno użyć odrębnego słowa kluczowego, gdy chcę go zastosować do wielu kolumn. Na przykład chcę uzyskać listę odrębnych firstName, lastName, a następnie grupowanie według po prostu zadziała. W tym przypadku miałem trudności z użyciem odrębnego.
Mam odpowiedź na Hibernate Query Language, aby używać odrębnych pól. Możesz użyć * SELECT DISTINCT (TO_CITY) FROM FLIGHT_ROUTE *. Jeśli używasz zapytania SQL , zwraca listę ciągów. Nie można jej użyć zwracanej wartości przez klasę jednostki. Zatem odpowiedzią na ten typ problemu jest użycie języka HQL z SQL .
FROM FLIGHT_ROUTE F WHERE F.ROUTE_ID IN (SELECT SF.ROUTE_ID FROM FLIGHT_ROUTE SF GROUP BY SF.TO_CITY);
Z SQL zapytania otrzymano DISTINCT ROUTE_ID i wprowadzono jako listę. A zapytanie IN filtruje odrębne TO_CITY z IN (Lista).
Typ zwrotu to typ Entity Bean. Więc możesz to zrobić w AJAX, takim jak AutoComplement .
Może wszystko będzie w porządku
Możesz w ten sposób określić odrębne słowo kluczowe w konstruktorze kryteriów.
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));
I utwórz konstruktora pola w swojej klasie modelu.
Jeśli potrzebujesz nowego słowa kluczowego dla niestandardowego DTO w instrukcji select i potrzebujesz odrębnych elementów , użyj nowego poza nowym, jak poniżej:
select distinct new com.org.AssetDTO(a.id, a.address, a.status) from Asset as a where ...