jpa specification 实现自定义字段的排序(附:MySQL的sql实现,代码实现暂未测试)

例如,有如下场景:
你需要根据table_a表的A字段的某些内容进行排序,让带有某些内容的数据优先显示,此时该字段A的内容并不是按照abcd这样的顺序进行排列,此时就需要用到自定义的排序操作。

先来看pgsql中的写法
SELECT a.A FROM table_a a ORDER BY CASE a.A WHEN '你好' THEN 1 WHEN '我好' THEN 2 WHEN '大家好' THEN 3 WHEN '是真滴好' THEN 4 END ASC
此时等于WHEN后面的字段内容就会按照THEN后面的1234的顺序进行ASC升序排序。

java代码实现:

	public ReturnType methodName(Integer page, Integer size, String string) throws Exception {

        Pageable pageable = new PageRequest(page, size);

        ReturnType returnType = repository.findAll(new Specification<ReturnType>() {
            @Override
            public Predicate toPredicate(Root<ReturnType> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                
                List<Predicate> list = new ArrayList<Predicate>()

                if (!StringUtils.isEmpty(string)) {
                    list.add(cb.equal(root.get("string").as(String.class), string));
                }

                List<Order> orders = new ArrayList<>();

                // 按状态排序,排序顺序是PipelineState枚举类的顺序
                orders.add(cb.asc(cb.selectCase()
                        .when(cb.equal(root.get("(要排序的实体类中的属性名字1)").as(该属性的类型.class), 需要相等的值),1)
                        .when(cb.equal(root.get("(要排序的实体类中的属性名字1)").as(该属性的类型.class),需要相等的值),2)
                        .when(cb.equal(root.get("(要排序的实体类中的属性名字1)").as(该属性的类型.class),需要相等的值),3)
                        .when(cb.equal(root.get("(要排序的实体类中的属性名字1)").as(该属性的类型.class),需要相等的值),4)
                        .otherwise(5)));
                orders.add(cb.desc(root.get("(要排序的实体类中的属性名字1)")));
                query.orderBy(orders);

                Predicate[] p = new Predicate[list.size()];

                return query.where(cb.and(list.toArray(p))).getGroupRestriction();
            }
        },pageable);

        return returnType;
    }

所有的字段的名字、类型都被我替代了。对号入座就行。
创建了一个Order的List集合是因为这里排序规则有两种。
该specification的自定义排序使用的数据库是pgsq。

接下来看一下mysql中的自定义排序的sql写法。

SELECT * FROM table_name ORDER BY FIELD(str,str1,str2,str3,...)

为了数据库的性能等方面,尽量不要使用 * 代替所有字段,此处只是为了演示。
str 填写 fieldName(字段名) 后面按照你心中所想的顺序依次填写上需要和该字段相等的值就行了。
java代码方面还没有实现过。测试了会补上。

上一篇:vue+element模拟百度搜索(输入建议)


下一篇:CB Insights:量子计算将改变的9大行业