Як створити чіткий запит у HQL


100

Чи є спосіб створити чіткий запит у HQL. Або за допомогою ключового слова "окремо" або якогось іншого методу. Я не впевнений, чи розрізнення є дійсним ключовим завданням для HQL, але я шукаю HQL-еквівалент ключового слова SQL "окремий".

Відповіді:


124

Ось фрагмент 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});

Я тільки коли-небудь використовував сплячку з MySQL - не знаю, як боротися з проблемою mssql.
Ноги

56

Варто зазначити, що 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.



16

зробити щось подібне наступного разу

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

 List claz = crit.list();

Це неоптимально: замість того, щоб відкинути повтори на рівні бази даних, вона просто перетягне дані з бази даних в пам’ять з повторами і все, а потім відкине повторення після цього; залежно від частоти повторення даних, це може значно збільшити операції вводу / виводу.
Haroldo_OK

9

Ви також можете використовувати Criteria.DISTINCT_ROOT_ENTITYз Hibernate HQL-запитом.

Приклад:

Query query = getSession().createQuery("from java_pojo_name");
query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return query.list();

1
Це неоптимально: замість того, щоб відкинути повтори на рівні бази даних, вона просто перетягне дані з бази даних в пам’ять з повторами і все, а потім відкине повторення після цього; залежно від частоти повторення даних, це може значно збільшити операції вводу / виводу.
Haroldo_OK

4

У мене виникли деякі проблеми з трансформаторами результатів у поєднанні з HQL-запитами. Коли я спробував

final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);

це не спрацювало. Мені довелося перетворити вручну так:

final List found = trans.transformList(qry.list());

З Criteria API трансформатори працювали просто чудово.


дістатися до 10k (:
timmz

3

Мій основний запит виглядав так у моделі:

@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;       
}

Я сподіваюся, що це допомогло! Знову ж таки, це може спрацювати лише у тому випадку, якщо ви дотримуєтесь методів кодування, що реалізують тип послуги, дао та модель.


2

Припустимо, у вас є об'єкт клієнта, відображений у таблиці CUSTOMER_INFORMATION, і ви хочете отримати список різних імен клієнтів. Ви можете використовувати фрагмент нижче, щоб отримати той самий.

Query distinctFirstName = session.createQuery("select ci.firstName from Customer ci group by ci.firstName");
Object [] firstNamesRows = distinctFirstName.list();

Я сподіваюся, що це допомагає. Отже, тут ми використовуємо групу замість того, щоб використовувати ключове слово.

Також раніше мені було важко використовувати окреме ключове слово, коли я хочу застосувати його до кількох стовпців. Наприклад, я хочу отримати список різних firstName, lastName, а потім група by просто працювала. У мене виникли труднощі з використанням чіткого в цьому випадку.


1

У мене є відповідь на мову 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, наприклад, Автозаповнення .

Може все буде гаразд


1

Ви можете виділити таке ключове слово у вашому конструкторі критеріїв, як це.

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));

І створити конструктор поля у вашому класі моделей.


0

Якщо вам потрібно використовувати нове ключове слово для користувацького DTO у своєму операторі select, і вам потрібні окремі елементи , використовуйте нове поза новим, наприклад, як:

select distinct new com.org.AssetDTO(a.id, a.address, a.status) from Asset as a where ...

0

Ви можете просто додати GROUP BY замість відмітного

@Query(value = "from someTableEntity where entityCode in :entityCode" +
            " group by entityCode, entityName, entityType")
List<someTableEntity > findNameByCode(@Param("entityCode") List<String> entityCode);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.