sql - 自定义order by条件的Criteria查询

标签 sql hibernate jpa spring-data-jpa

我正在尝试按字段对数据进行排序

查询:

select * from user
where (location = "%loc%" and role = "TECH")
order by field (department, "ELEC", "MECH");

我为 order by 字段创建了自定义 Order 类,如果我提供两个 where 条件 Order by 不起作用并返回 0 条记录,则它仅在单个 where 条件下工作正常。

如果我删除订单,它会返回预期结果。

USER TABLE
    ______________________________________________________
    |NAME    | AGE  | ROLE       | DEPARTMENT | LOCATION  |
    |________|______|____________|____________|___________|
    |name1   |  24  | TECH       | MECH       | location1 |
    |name2   |  25  | TECH       | ELEC       | location2 |
    |name3   |  26  | TECH       | COMP       | location3 |
    |name4   |  27  | NONTECH    | CVL        | location4 |
    -------------------------------------------------------

*** EXPECTED RESULT ***
    ______________________________________________________
    |NAME    | AGE  | ROLE       | DEPARTMENT | LOCATION  |
    |________|______|____________|____________|___________|
    |name2   |  25  | TECH       | ELEC       | location2 |
    |name1   |  24  | TECH       | MECH       | location1 |
    |name3   |  26  | TECH       | COMP       | location3 |
    ------------------------------------------------------


import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Order;

public class OrderByField implements Order {

    private Expression<?> expression;

    @Override
    public Order reverse() {
        return null;
    }

    @Override
    public boolean isAscending() {
        return true;
    }

    @Override
    public Expression<?> getExpression() {
        return expression;
    }

    public OrderByField(CriteriaBuilder cb, List<Expression<?>> list) {
        this.expression = cb.function("field", String.class, list.toArray(new Expression<?>[list.size()]));
    }
}

标准逻辑

    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<User> criteriaQuery = builder.createQuery(User.class);
    Root<User> userData = criteriaQuery.from(User.class);

    //Order By field DEPARTMENT
    List<Expression<?>> departmentList = new ArrayList<>();
    departmentList.add(userData.get("department"));
    departmentList.add(builder.parameter(String.class, "param1"));
    departmentList.add(builder.parameter(String.class, "param2"));

    OrderByField order = new OrderByField(builder, departmentList); //custom class for ordeBy field

    //WHERE CLUASE for location and role

    List<Predicate> predicates = new ArrayList<>();
    predicates.add(builder.like(userData.get("location"), "%" + "loc" + "%"));
    predicates.add(builder.like(userData.get("role"), "%" + "TECH" + "%"));

    criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));
    criteriaQuery.orderBy(order);

    TypedQuery<User> query = em.createQuery(criteriaQuery);

    //ORDER BY FIELD PARAMS
    query.setParameter("param1", "ELEC");
    query.setParameter("param2", "MECH");

    return query.getResultList();

** 用户实体 **

 public class User {

        @Column(name =  "NAME")
        private String name;

        @Column(name =  "AGE")
        private String age;

        @Column(name =  "ROLE")
        private String role;

        @Column(name =  "DEPARTMENT")
        private String department;

        @Column(name =  "LOCATION")
        private String location;
}

最佳答案

可以通过以下方式解决:

1) 声明 OrderByField 类,如下所示:

import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Order;

public class OrderByField implements Order
{
   private Expression<?> expression;

   public OrderByField(Expression<?> expression)
   {
      this.expression = expression;
   }

   @Override
   public Order reverse()
   {
      return null;
   }

   @Override
   public boolean isAscending()
   {
      return true;
   }

   @Override
   public Expression<?> getExpression()
   {
      return expression;
   }
}

2) 创建以下CriteriaQuery:

CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<User> criteria = builder.createQuery(User.class);
Root<User> root = criteria.from(User.class);

criteria.select(root);
criteria.where(
   builder.and(
      builder.like(root.get("location"), "%loc%"),
      builder.equal(root.get("role"), "TECH")
   )
);

Expression<Integer> ord = builder.function(
   "field",
   Integer.class,
   root.get("department"),
   builder.literal("ELEC"),
   builder.literal("MECH")
);
OrderByField order = new OrderByField(ord);
criteria.orderBy(order);

List<User> result = session.createQuery(criteria).getResultList();

您将得到以下结果:

User (3, COMP)
User (2, ELEC)
User (1, MECH)

关于sql - 自定义order by条件的Criteria查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59811868/

相关文章:

java - Hive 描述分区以显示分区 url

mysql - sql插入一直报错

mysql - SQL - 按 'datetime' DESC 排序

java - 无法 Autowiring 存储库字段

hibernate - Grails java.lang.IllegalStateException : Method on class [] was used outside of a Grails application

java - jpa AttributeConverter 是否适用于查询子句?

mysql - 连接mysql上的两个表

hibernate - Hibernate session 工厂找不到 DAO 注释中定义的 NamedQuery

java - @JoinTable 连接三个表

java - JPA表中的ID是强制的吗?