Відповіді:
Ось фрагмент hql, який ми використовуємо. (Імена змінено для захисту особи)
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});
Варто зазначити, що distinct
ключове слово в HQL не відображається безпосередньо до distinct
ключового слова в SQL.
Якщо ви використовуєте distinct
ключове слово в HQL, іноді Hibernate використовуватиме distinct
ключове слово SQL, але в деяких ситуаціях він використовує трансформатор результатів для отримання чітких результатів. Наприклад, коли ви використовуєте зовнішнє з'єднання, як це:
select distinct o from Order o left join fetch o.lineItems
У цьому випадку неможливо відфільтрувати дублікати на рівні SQL, тому Hibernate використовує a ResultTransformer
для фільтрації дублікатів після виконання запиту SQL.
зробити щось подібне наступного разу
Criteria crit = (Criteria) session.
createCriteria(SomeClass.class).
setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
List claz = crit.list();
Ви також можете використовувати Criteria.DISTINCT_ROOT_ENTITY
з Hibernate HQL-запитом.
Приклад:
Query query = getSession().createQuery("from java_pojo_name");
query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return query.list();
У мене виникли деякі проблеми з трансформаторами результатів у поєднанні з HQL-запитами. Коли я спробував
final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);
це не спрацювало. Мені довелося перетворити вручну так:
final List found = trans.transformList(qry.list());
З Criteria API трансформатори працювали просто чудово.
Мій основний запит виглядав так у моделі:
@NamedQuery(name = "getAllCentralFinancialAgencyAccountCd",
query = "select distinct i from CentralFinancialAgencyAccountCd i")
І я все ще не отримував тих, що вважав «виразними» результатами. Вони просто відрізнялися на основі комбінації первинних ключів на столі.
Тож DaoImpl
я додав зміну в один рядок і в кінцевому підсумку отримував "чітке" повернення, яке я хотів. Прикладом може бути замість того, щоб бачити 00 чотири рази, тепер я просто бачу це один раз. Ось код, який я додав до 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;
}
Я сподіваюся, що це допомогло! Знову ж таки, це може спрацювати лише у тому випадку, якщо ви дотримуєтесь методів кодування, що реалізують тип послуги, дао та модель.
Припустимо, у вас є об'єкт клієнта, відображений у таблиці CUSTOMER_INFORMATION, і ви хочете отримати список різних імен клієнтів. Ви можете використовувати фрагмент нижче, щоб отримати той самий.
Query distinctFirstName = session.createQuery("select ci.firstName from Customer ci group by ci.firstName");
Object [] firstNamesRows = distinctFirstName.list();
Я сподіваюся, що це допомагає. Отже, тут ми використовуємо групу замість того, щоб використовувати ключове слово.
Також раніше мені було важко використовувати окреме ключове слово, коли я хочу застосувати його до кількох стовпців. Наприклад, я хочу отримати список різних firstName, lastName, а потім група by просто працювала. У мене виникли труднощі з використанням чіткого в цьому випадку.
У мене є відповідь на мову Hibernate Query для використання чітких полів. Ви можете використовувати * SELECT DISTINCT (TO_CITY) Flight_ROUTE *. Якщо ви використовуєте SQL- запит, він повертає список рядків. Ви не можете використовувати його повернене значення за класом особи. Таким чином, відповідь для вирішення цього типу проблеми полягає у використанні HQL із SQL .
FROM FLIGHT_ROUTE F WHERE F.ROUTE_ID IN (SELECT SF.ROUTE_ID FROM FLIGHT_ROUTE SF GROUP BY SF.TO_CITY);
Із оператора запиту SQL він отримав DISTINCT ROUTE_ID і введений як список. І за запитом фільтруйте окремий TO_CITY з IN (Список).
Тип повернення - тип Entity Bean. Таким чином, ви можете це в AJAX, наприклад, Автозаповнення .
Може все буде гаразд
Ви можете виділити таке ключове слово у вашому конструкторі критеріїв, як це.
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));
І створити конструктор поля у вашому класі моделей.
Якщо вам потрібно використовувати нове ключове слово для користувацького DTO у своєму операторі select, і вам потрібні окремі елементи , використовуйте нове поза новим, наприклад, як:
select distinct new com.org.AssetDTO(a.id, a.address, a.status) from Asset as a where ...