繁体   English   中英

Hibernate 命名查询 Order By 参数

[英]Hibernate Named Query Order By parameter

谁能指出我们如何将 order by 子句作为命名参数传递给 HQL?

工作示例:

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

不支持,只能在WHEREHAVING子句中使用输入参数,不能在ORDER BY子句中使用参数。 或者,如果我改写,您不能对列使用参数,只能使用值。 所以,要么:

  • 有尽可能多的命名查询排序顺序
  • 将排序字符串连接到查询字符串
  • 使用条件查询

尝试在没有 order by 子句的情况下存储命名查询,获取查询字符串并在运行时添加 order by 子句片段。

Brian Fields 在他的博客中解释了它: 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;
}

您可能希望将排序字段限制为模型中的排序字段。 在我的项目中,我静态地做到了这一点:

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

在将字符串连接到 jpql 或 hql 之前验证 DAL 上的字段名称,您将避免 sql 注入或进一步的问题

这在 MySQL 中对我有用:

ORDER BY CASE :orderby WHEN 0 THEN field_x WHEN 1 THEN field_y ELSE field_z END ASC

可以这样做

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

您可以像这样在 setString 函数中传递“pato_id”或“last_update_dt”

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

这适用于 MS SQL Server,不确定其他人。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM