简体   繁体   English

JPA条件查询API,最后按null排序

[英]JPA Criteria Query API and order by null last

My problem is null values must be last order by statement. 我的问题是空值必须是按语句的最后顺序。 My code snipshot below. 我的代码片段如下。 I use javax persistance criteria builder. 我使用javax持久性条件构建器。 My query complicated. 我的查询很复杂。

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

How to achieve order by price null last with criteria builder ? 如何使用条件生成器按价格为空的顺序实现订单?

Hi I almost search all internet pages and then find a solution, you can write switch case order by part. 嗨,我几乎搜索了所有互联网页面,然后找到了解决方案,您可以按部分编写开关案例的顺序。 like below: to order by desc if price is null, price value is 1000000, and to order by asc if price is null, price value is 0. if you want these, you can write expression like below. 如下所示:如果price为空,则按desc排序,价格值为1000000,如果price为空,则按asc排序,价格值为0。如果需要这些,则可以编写如下表达式。

                EOrderByType orderType = EOrderByType.values()[orderBy];                    
                Expression<Object> 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));

This is a bit of an extension to katsu's answer to his own question. 这是katsu对自己问题的回答的扩展。 I was trying to find a solution to being able to sort most of the columns of a table where some columns are allowed to have null values. 我试图找到一种解决方案,能够对表的大多数列进行排序,其中某些列允许具有空值。 I wanted to sort the null values in front of the lowest non-null values when sorting in ascending order and after the lowest non-null values when sorting in descending order. 我想按升序排序时,将空值放在最低的非空值前面,而当按降序排序时,要在最低的非空值之后。 In other words, pretty much the opposite of the (Oracle's) default behavior. 换句话说,这与(Oracle的)默认行为截然相反。

I found other methods that might do this, but this one didn't require me to go outside of Hibernate and JPA 2 persistence, but still get the results I wanted. 我找到了其他方法可以做到这一点,但是这种方法不需要我脱离Hibernate和JPA 2持久性,但仍然可以获得我想要的结果。 This is a snippet of code taken from my actual code, but consolidated in one spot and with some names changed. 这是摘录自我的实际代码的一小段代码,但合并在一个位置,并且更改了一些名称。 Any syntax, compilation-type errors you see are probably due to that. 您看到的任何语法,编译类型错误都可能是由于该原因。

// 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<SoftwareVersion> criteriaQuery and 
// CriteriaBuilder criteriaBuilder by the typical means.

final Root<SoftwareVersion> softwareVersionRoot = 
    criteriaQuery.from(SoftwareVersion.class);

private static final String EMPTY_STRING = "";

if (sortByColumn != null && sortByColumn.trim().length() > 0) {
  Order sortOrder;
  Expression<String> 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<String> 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<Object> 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);
}

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

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