Spring Boot中如何使用orderBy实现自定义排序?
问题
我无法将以下SQL查询转换为对应的Spring查询语句:
SELECT person_name, role FROM persons GROUP BY person_name, role ORDER BY ROLE = 'viewer', ROLE = 'participant', ROLE = 'collaborator', ROLE = 'lead';
我尝试了如下写法,但没有效果:
select(field("person_name"), field("role")) .from(table("person")) .groupBy(field("person_name"), field("role")) .orderBy((field("role").equals("viewer")).and(field("role").equals("participant")).and( field("role").equals("collaborator")).and(field("role").equals("lead"))));
如果直接使用orderBy(role),得到的是字典序升序结果:collaborator > lead > participant > viewer,但我期望的排序顺序是lead > collaborator > participant > viewer。
解决方案
你的核心问题是没理解原SQL排序逻辑的本质,以及Spring查询构造器中排序条件的正确写法。以下两种方法可以实现你要的排序:
方法1:拆分排序条件并降序排列
原SQL的ORDER BY是逐个判断角色匹配,默认升序下false(不匹配)排在true(匹配)前面。要实现lead优先,只需把排序条件的顺序反过来,每个条件单独用降序:
select(field("person_name"), field("role")) .from(table("persons")) // 注意原SQL表名是persons,你之前写的person是笔误 .groupBy(field("person_name"), field("role")) .orderBy(field("role").eq("lead").desc()) .orderBy(field("role").eq("collaborator").desc()) .orderBy(field("role").eq("participant").desc()) .orderBy(field("role").eq("viewer").desc());
每个eq()会生成role = 'xxx'的布尔表达式,desc()让匹配成功的记录排在前面,刚好符合你的排序要求。
方法2:用CASE WHEN定义排序权重
这种方式可读性更强,给每个目标角色分配权重,权重越高排序越靠前:
select(field("person_name"), field("role")) .from(table("persons")) .groupBy(field("person_name"), field("role")) .orderBy( case_() .when(field("role").eq("lead"), 4) .when(field("role").eq("collaborator"), 3) .when(field("role").eq("participant"), 2) .when(field("role").eq("viewer"), 1) .otherwise(0) .desc() );
后续要调整排序顺序,只需修改对应的权重数值即可。
你的原写法错误原因
你用.and()把所有角色匹配条件连在一起,生成的SQL是(role = 'viewer' AND role = 'participant' AND role = 'collaborator' AND role = 'lead'),这逻辑永远为假,自然起不到排序作用。必须把每个排序条件单独作为orderBy子句,或者用CASE WHEN统一处理。
内容的提问来源于stack exchange,提问作者Fazeel Usmani
相关产品推荐
相关产品推荐

