JPA Criteria Query API并且最后按null排序

我的问题是空值必须是最后一个按语句排序。 我的代码在下面拍了一下。 我使用javax持久标准构建器。 我的查询很复杂。

import javax.persistence.criteria.CriteriaBuilder; public Predicate getSomePredicate() { Predicate predicate = cb.conjunction();.... ...predicate.getExpressions().add(cb.and(cb.or(cb.and(v1, v2), cb.and(s1, s2)))); EOrderByType orderType = EOrderByType.values()[orderBy] ; switch (orderType) { case PRICE: cq.where(predicate).orderBy(cb.asc(root.get("price"))); break; case PRICE_HIGH_TO_LOW: cq.where(predicate).orderBy(cb.desc(root.get("price"))); break; case CONSUPTION: cq.where(predicate).orderBy(cb.desc(root.get("consume"))); break; default: break; } return cq.getRestriction(); } 

如何使用条件生成器按价格实现订单空?

这是对katsu回答他自己问题的一点延伸。 我试图找到一种解决方案,能够对表的大多数列进行排序,其中某些列可以具有空值。 我想按升序排序时在最低非空值前面排序空值,在按降序排序时排序最低非空值。 换句话说,几乎与(Oracle的)默认行为相反。

我发现其他方法可能会这样做,但是这个方法并不需要我超出Hibernate和JPA 2持久性,但仍然得到我想要的结果。 这是从我的实际代码中获取的代码片段,但在一个位置合并并更改了一些名称。 您看到的任何语法,编译类型错误都可能是由于这一点。

 // sortByColumn is a String containing the Hibernate version of the column name, which had // been assigned as the ID of the table header column of the column by which we are sorting. // sortAscending is a Boolean object containing Boolean.TRUE if we are to sort in ascending // order or Boolean.FALSE or null if we are to sort in descending order. This may seem a // bit odd, but in the case we need this for, the default sort column is a release date and // reverse chronological order is the most useful in that case. // Also defined are: CriteriaQuery criteriaQuery and // CriteriaBuilder criteriaBuilder by the typical means. final Root softwareVersionRoot = criteriaQuery.from(SoftwareVersion.class); private static final String EMPTY_STRING = ""; if (sortByColumn != null && sortByColumn.trim().length() > 0) { Order sortOrder; Expression sortColumnExpression; if (sortByColumn.equalsIgnoreCase(SoftwareVersion_.installationFileLength.getName()) || sortByColumn.equalsIgnoreCase(SoftwareVersion_.releaseTimestamp.getName())) { // The two non-String fields (exposed to the user) that we don't need to have the // lower() function operate upon. sortColumnExpression = oemSoftwareVersionRoot.get(sortByColumn); } else { // We use the lower() function to enforce case insensitive sorting on the columns we // show to the user, which are all Strings except as noted above. Expression rootExpression = oemSoftwareVersionRoot.get(sortByColumn); sortColumnExpression = criteriaBuilder.lower(rootExpression); } // The columns for installation file name, installation file length and release timestamp // are just three of the columns that we allow the user to sort by. However, these three // may have null values in the database, and require some special handling. if (sortByColumn.equalsIgnoreCase(SoftwareVersion_.installationFileLength.getName()) || sortByColumn.equalsIgnoreCase(SoftwareVersion_.installationFileName.getName()) || sortByColumn.equalsIgnoreCase(SoftwareVersion_.releaseTimestamp.getName()) ) { Expression queryCase; if (sortByColumn.equalsIgnoreCase(SoftwareVersion_.installationFileName.getName())) { // Installation file name is a (case insensitive) String queryCase = criteriaBuilder.selectCase().when( criteriaBuilder.isNull(sortColumnExpression), StringUtil.EMPTY_STRING).otherwise(sortColumnExpression); } else if (sortByColumn.equalsIgnoreCase(SoftwareVersion_.releaseTimestamp.getName())) { // Release timestamp is a database timestamp LocalDateTime dateTime = LocalDateTime.of(1970,1,1,0,0); // Equivalent to Unix epoch time. Note month is 1-12, not 0-11 queryCase = criteriaBuilder.selectCase().when( criteriaBuilder.isNull(sortColumnExpression), Timestamp.valueOf(dateTime)).otherwise(sortColumnExpression); } else { // Installation file length is a Long (or BigDecimal) computed when the file is uploaded. // The user can't set or change it, but can sort by it. queryCase = criteriaBuilder.selectCase().when( criteriaBuilder.isNull(sortColumnExpression), Long.valueOf(0)).otherwise(sortColumnExpression); } if (asc != null && asc.booleanValue()) { sortOrder = criteriaBuilder.asc(queryCase); } else { sortOrder = criteriaBuilder.desc(queryCase); } } else { if (asc != null && asc.booleanValue()) { sortOrder = criteriaBuilder.asc(sortColumnExpression); } else { sortOrder = criteriaBuilder.desc(sortColumnExpression); } } criteriaQuery.orderBy(sortOrder); } 

嗨,我几乎搜索所有的网页,然后找到一个解决方案,你可以按部分编写switch case。 如下所示:如果价格为空,则按desc订购,价格值为1000000,如果价格为空,则按asc订购,价格值为0.如果您需要这些,您可以写下面的表达式。

  EOrderByType orderType = EOrderByType.values()[orderBy]; Expression queryCase = cb.selectCase().when(cb.isNull(root.get("price")), 100000000).otherwise(root.get("price")); Direction dir = Direction.ASC; switch (orderType) { case UCUZDAN_PAHALIYA: queryCase = cb.selectCase().when(cb.isNull(root.get("price")), 100000000).otherwise(root.get("price")); break; case PAHALIDAN_UCUZA: queryCase = cb.selectCase().when(cb.isNull(root.get("price")), 0).otherwise(root.get("price")); dir = Direction.DESC; break; } cq.where(predicate).orderBy(direction( cb, queryCase, dir));