Spring Boot+MyBatis如何构建多条件运算符的查询语句
实现多条件运算符的学生查询方案
针对你的需求,这里提供两种基于原生MyBatis的实现方案,无需引入额外框架:
方案一:拆分条件字段,直观定义查询参数
这种方式通过自定义查询DTO,把不同的条件拆分成独立字段,逻辑清晰,易于维护。
1. 创建查询参数类
新建StudentQuery类,封装年龄的各类查询条件:
public class StudentQuery { // 原等于查询条件 private Integer age; // 年龄大于 private Integer ageGt; // 年龄小于 private Integer ageLt; // 年龄区间起始值(between) private Integer ageStart; // 年龄区间结束值(between) private Integer ageEnd; // getter、setter方法省略 }
2. 调整各层方法参数
依次修改DAO、Service、Controller的方法,将原Student参数替换为StudentQuery:
// StudentDao List<Student> listStudent(StudentQuery query, Pageable pageable); // StudentService List<Student> listStudent(StudentQuery query, Pageable pageable) { return this.studentDao.listStudent(query, pageable); } // StudentController List<Student> listStudent(StudentQuery query, Pageable pageable) { return this.studentService.listStudent(query, pageable); }
3. 编写动态SQL
修改MyBatis的XML映射文件,通过<if>标签判断不同条件是否生效,自动拼接SQL:
<select id="listStudent" resultType="student"> select * from student <where> <!-- 等于条件 --> <if test="age != null"> age = #{age} </if> <!-- 大于条件 --> <if test="ageGt != null"> <if test="age != null">AND</if> age > #{ageGt} </if> <!-- 小于条件 --> <if test="ageLt != null"> <if test="age != null or ageGt != null">AND</if> age < #{ageLt} </if> <!-- 区间条件 --> <if test="ageStart != null and ageEnd != null"> <if test="age != null or ageGt != null or ageLt != null">AND</if> age between #{ageStart} and #{ageEnd} </if> </where> <!-- 处理分页与排序 --> <if test="pageable.sort != null"> order by <foreach item="order" collection="pageable.sort" separator=","> ${order.property} ${order.direction} </foreach> </if> limit #{pageable.offset}, #{pageable.pageSize} </select>
补充说明
- 可以在Service层添加参数校验逻辑,避免冲突条件(如同时传入
age和ageStart),防止生成不符合预期的SQL。 - 客户端调用时,只需传入对应条件字段即可,比如查询
age>10就传ageGt=10,查询区间就传ageStart=10和ageEnd=12。
方案二:用枚举定义运算符,灵活适配多场景
这种方式通过枚举统一管理运算符,单个字段可适配多种查询逻辑,适合需要灵活切换运算符的场景。
1. 定义运算符枚举
public enum Operator { EQ, // 等于 GT, // 大于 LT, // 小于 BETWEEN // 区间 }
2. 创建带运算符的查询类
public class StudentQuery { private Integer age; // 区间查询的第二个值 private Integer ageSecondValue; // 年龄对应的查询运算符 private Operator ageOperator; // getter、setter方法省略 }
3. 编写动态SQL
通过<choose>标签根据运算符拼接对应SQL片段:
<select id="listStudent" resultType="student"> select * from student <where> <if test="age != null"> age <choose> <when test="ageOperator == 'EQ'">= #{age}</when> <when test="ageOperator == 'GT'">> #{age}</when> <when test="ageOperator == 'LT'">< #{age}</when> <when test="ageOperator == 'BETWEEN'">between #{age} and #{ageSecondValue}</when> <!-- 默认使用等于查询 --> <otherwise>= #{age}</otherwise> </choose> </if> </where> <!-- 分页与排序逻辑同方案一 --> <if test="pageable.sort != null"> order by <foreach item="order" collection="pageable.sort" separator=","> ${order.property} ${order.direction} </foreach> </if> limit #{pageable.offset}, #{pageable.pageSize} </select>
补充说明
- 业务层需校验运算符与参数的匹配性,比如使用
BETWEEN时必须传入ageSecondValue,否则抛出参数异常。 - 客户端调用时,只需指定
age、ageOperator(及对应辅助参数)即可实现不同条件查询。
内容的提问来源于stack exchange,提问作者frank
相关产品推荐
相关产品推荐

