Hibernate Named Query Order By параметром - PullRequest
18 голосов
/ 08 ноября 2010

Привет, может кто-нибудь указать мне, как мы можем передать заказ по предложению в качестве именованного параметра в hql

Ex:

Работает:

select tb from TransportBooking as tb

and TIMESTAMP(tb.bookingDate, tb.bookingTime) >= current_timestamp() order by tb.bookingDate

Не работает:

select tb from TransportBooking as tb

and TIMESTAMP(tb.bookingDate, tb.bookingTime) >= current_timestamp() order by :order

Ответы [ 5 ]

25 голосов
/ 08 ноября 2010

Не поддерживается, входные параметры разрешены только в предложениях WHERE и HAVING, и вы не можете использовать параметры для предложения ORDER BY.Или, если я перефразирую, вы не можете использовать параметры для столбцов, только значения.Итак, либо:

  • Иметь как можно больше именованных запросов, насколько это возможно, порядков сортировки.
  • . Конкатенировать строку заказа в строку запроса.*
6 голосов
/ 10 июня 2011

Попробуйте сохранить именованный запрос без предложения order by, получить строку запроса и добавить порядок по частям предложения во время выполнения.

Брайан Филдс объяснил это в своем блоге: http://brainfields.blogspot.com/2009/08/order-by-in-hibernate-named-queries.html

Я собрал идею для своего проекта:

private static final Pattern badQueryPattern = Pattern.compile("[^\\p{ASCII}]*");

public static String getNamedQueryString(EntityManager em, String queryName) throws SQLException {
    Query tmpQuery = em.createNamedQuery(queryName);
    SQLQuery sqlQuery = tmpQuery.unwrap(SQLQuery.class);
    String queryString = sqlQuery.getQueryString();
    if (badQueryPattern.matcher(queryString).matches()) {
        throw new SQLException("Bad query string.");
    }

    return queryString;
}


public static Query getNamedQueryOrderedBy(EntityManager em, String queryName, Map<String, Boolean> columnNames) throws SQLException {

    StringBuilder sb = new StringBuilder();
    sb.append(ORDER_BY_CLAUSE_START);

    int limit = columnNames.size();
    int i = 0;
    for (String columnName: columnNames.keySet()) {
        sb.append(columnName);

        if (columnNames.get(columnName))
            sb.append(" ASC");
        else
            sb.append(" DESC");

        if (i != (limit - 1)) {
            sb.append(", \n");
        }
    }
    Query jpaQuery = em.createNativeQuery( getNamedQueryString(em, queryName)
                + sb.toString() 
                );

    return jpaQuery;
}
2 голосов
/ 04 декабря 2012

Возможно, вы захотите ограничить поле сортировки теми, которые есть в вашей модели.В моем проекте я делал это статически:

public static boolean isColumnName(Object domain, String columnName) {
    Field[] fields = domain.getClass().getDeclaredFields();
    for (Field field : fields) {
        Annotation[] annotations = field.getAnnotations();
        for (Annotation annotation : annotations) {
            if (annotation instanceof Column) {
                Column column = (Column) annotation;
                String foundColumnName;
                if (column.name() != null && !column.name().isEmpty()) {
                    foundColumnName = column.name();
                } else {
                    foundColumnName = field.getName();
                }
                if (columnName.toUpperCase().equals(
                    foundColumnName.toUpperCase())) {
                    return true;
                }
            }
        }
    }
    return false;
}   

Проверяя имя поля на вашем DAL перед конкатенацией строки в jpql или hql, вы избежите внедрения SQL или дальнейших проблем

0 голосов
/ 30 января 2019

Это работает для меня в MySQL:

ORDER BY CASE :orderby WHEN 0 THEN field_x WHEN 1 THEN field_y ELSE field_z END ASC
0 голосов
/ 26 декабря 2014

Это можно сделать следующим образом

 order by CASE :orderBy
          WHEN 'pato_id' THEN PATO.id
          WHEN 'last_update_dt' THEN PATO.last_update_dt
     END desc

, и вы можете передать "pato_id" или "last_update_dt" в функцию setString следующим образом

 q.setString("orderBy", "last_update_dt");
 or
 q.setString("orderBy", "pato_id");

Это работает с MS SQL Server, не уверен насчет других.

...