Hibernate命名查询顺序依据参数

嗨,任何人都可以指出我们如何将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 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之前validationDAL上的字段名称将避免sql注入或进一步的问题

它可以这样做

  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,不确定其他人。