问题处理-JPA使用CASE...WHEN...语句实现数据排序问题

正常我们在使用JPA查询的时候,代码一般是这样

public List findAllUsers() {
        List users = sysUserRepository.findAll(new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {

                List predicateList = new ArrayList<>();
                predicateList.add(criteriaBuilder.isFalse(root.get("isDeleted")));
                query.distinct(true);
                query.where(predicateList.toArray(new Predicate[predicateList.size()]));
                query.orderBy(criteriaBuilder.desc(root.get("createDate")));
                return query.getRestriction();
            }
        });
        return users;
    }

其中的查询排序只能根据其中某一个属性或者多个属性进行升序或者降序处理
控制台也会打印的执行SQL:

... ... order by sysuser0_.create_date desc

这样在有些特殊的需求就无法满足了,例如:假如客户需求是要求某些住在特定地点的用户信息优先显示出来,这样JPA查询中单纯的升序和降序就无法满足了。
因此,这里提出了三种解决方案:

一、构造新的属性字段用于排序
为用户类添加一个新的属性,特殊用户赋予一个定值,其他用户赋予其他值,再根据这个属性进行排序;个人觉得这样方法比较适用于项目初期开发构建的时候使用,因为这个新的属性在用户创建或者更改住址信息的时候,都需要做处理,一个已经进行到一定程度的项目,再去添加新属性,也许会有遗漏,后续开发者做关联开发的时候也容易忽略这个问题

二、使用原生的SQL去执行查询语句
JPA查询,也支持原生的SQL执行查询,原生SQL虽然少了JPA查询的便利,但是速度比较快,耗费资源也比较小。原生的SQL语句有多种方式可以让数据优先显示(使用的数据库是MySQL,其他类型数据库可以自行百度看看类似处理):

SELECT * FROM tab_sys_user ORDER BY user_address = '112' DESC

这种排序写法看上去好像是错误的,但是在数据库中,确实是可以执行的,它会优先显示满足条件的数据

SELECT * FROM tab_sys_user ORDER BY FIELD(user_address,112,01153) ASC

这种写法是调用的自带的FIELD函数,可以让数据按照指定列按照指定顺序去显示

SELECT * FROM tab_sys_user ORDER BY CASE WHEN user_address = '112' THEN 1 ELSE 0 END DESC

这种是利用了CASE…WHEN…的用法做数据排序,原理可以自行百度

三、使用CASE…WHEN…做处理
JPA查询也是支持CASE…WHEN…的相关操作的,实现原理和第二种方法里面的第三个SQL是一样的

query.orderBy(
    criteriaBuilder.desc(
        criteriaBuilder.selectCase()
        .when(criteriaBuilder.equal(root.get("address"),"112"),1)
        .otherwise(0)));

可以看到执行sql打印:

... ... order by case when sysuser0_.user_address=? then 1 else 0 end desc

可能还有其他方法,但是目前想到的就这三种了,只是提供了一个思路,大佬可以瞅瞅怎么使用JPA实现类似第二种方法的第二个SQL查询方式,传递一个集合,按照集合顺序去排序

你可能感兴趣的:(BUG篇,集成篇,后端篇)