Mybatis如何实现基于动态参数的排序功能?

2026-05-26 00:091阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计859个文字,预计阅读时间需要4分钟。

Mybatis如何实现基于动态参数的排序功能?

目录+ Mybatis实现动态排序+ Mybatis动态排序不生效问题+ 产生问题的原因+ 解决办法+ Mybatis实现动态排序+ 数据展示时,很可能会遇到,需要动态排序的需求。+ 当数据比较少的时候,还可以前端处理。

目录
  • Mybatis实现动态排序
  • Mybatis动态排序不生效问题
    • 造成问题原因
    • 解决办法

Mybatis实现动态排序

在数据展示时,很有可能碰到,需要动态排序的需求。当数据比较少的时候,还可以前端排序,但是,当数据非常大,尤其是涉及到分页的时候,就必须要用后端解决了。

以下,提供一种后端动态排序解决方案。

比如,现在我要查询用户信息(User)表。

可以在查询时,接口中,多添加两个字段。

  • orderField(排序列)
  • orderType(排序规则,升降序)

之后,在mapper.xml中的查询列表方法,添加

SELECT  name , sex , age , user_grade as userGrade FROM user <if test="orderField !=null and orderField != '' ">     order by ${orderField}  ${orderType} </if>

注意事项:使用这样连续拼接两个注入参数时,只能用${},不能用#{}。

详情可以查看解释

这时,在我们查询时,可以在传入参数

User user = new User(); //以user_grade字段排序 user.setOrderField("user_grade"); //降序 user.setOrderType("desc"); //可在User类中添加 //在未传入时,使用set注入,设置默认值 public String getOrderField() {         if (orderField == null || "".equals(orderField)) {             orderField = "create_time";         }         return orderField;     }     public String getOrderType() {         if (orderType == null || "".equals(orderType)) {             orderType = "desc";         }         return orderType;     }

如果,你觉得传入数据库中字段user_grade很不舒服的话。可以这样写SQL

SELECT  name , sex , age , user_grade as userGrade FROM user <if test="orderField != null" >     ORDER BY     <choose>         <when test="orderField == 'name'">             name ${orderType}         </when>         <when test="orderField == 'age'">             age ${orderType}         </when>         <when test="orderField == 'userGrade'">             user_grade ${orderType}         </when>         <otherwise>             create_time ${orderType}         </otherwise>     </choose> </if>

然后再传入字段时,就这样

user.setOrderField("userGrade");

Mybatis动态排序不生效问题

sql如下:

select * from  table_name order by #{field}

造成问题原因

mybatis动态参数

#{}方式传参数会使用preparedstatement预编译处理方式,参数是以?占位符的方式传递。可以看到mybaits的sql日志如下:

==> Preparing: SELECT * FROM table_name ORDER BY ? ==> Parameters: time(String)

preparedstatement预编译方式的参数替换的原理1可知预编译方式会对参数加上’'引号,生成的最终sql如下:

Mybatis如何实现基于动态参数的排序功能?

SELECT * FROM table_name ORDER BY 'time'

以上sql数据库不能正常解析 order by 后面的字段,这就是我们排序失效的原因

解决办法

将#{}参数方式改成${}参数方式即可。

原因: ${}参数的方式是简单的字符串替换。

在动态解析阶段,该 sql 语句会被解析成:

select * from table_name order by time

小结一下:

  • #{}方式传参数只能处理值参数 不能传递表名,字段等参数
  • ${}字符串替换,可以动态处理表名,字段参数,但是使用这种方式必须注意sql注入的风险,对参数做好校验处理

备注:preparedstatement具体实现原理见:com.mysql.jdbc.PreparedStatement中的setString方法源码

以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。

本文共计859个文字,预计阅读时间需要4分钟。

Mybatis如何实现基于动态参数的排序功能?

目录+ Mybatis实现动态排序+ Mybatis动态排序不生效问题+ 产生问题的原因+ 解决办法+ Mybatis实现动态排序+ 数据展示时,很可能会遇到,需要动态排序的需求。+ 当数据比较少的时候,还可以前端处理。

目录
  • Mybatis实现动态排序
  • Mybatis动态排序不生效问题
    • 造成问题原因
    • 解决办法

Mybatis实现动态排序

在数据展示时,很有可能碰到,需要动态排序的需求。当数据比较少的时候,还可以前端排序,但是,当数据非常大,尤其是涉及到分页的时候,就必须要用后端解决了。

以下,提供一种后端动态排序解决方案。

比如,现在我要查询用户信息(User)表。

可以在查询时,接口中,多添加两个字段。

  • orderField(排序列)
  • orderType(排序规则,升降序)

之后,在mapper.xml中的查询列表方法,添加

SELECT  name , sex , age , user_grade as userGrade FROM user <if test="orderField !=null and orderField != '' ">     order by ${orderField}  ${orderType} </if>

注意事项:使用这样连续拼接两个注入参数时,只能用${},不能用#{}。

详情可以查看解释

这时,在我们查询时,可以在传入参数

User user = new User(); //以user_grade字段排序 user.setOrderField("user_grade"); //降序 user.setOrderType("desc"); //可在User类中添加 //在未传入时,使用set注入,设置默认值 public String getOrderField() {         if (orderField == null || "".equals(orderField)) {             orderField = "create_time";         }         return orderField;     }     public String getOrderType() {         if (orderType == null || "".equals(orderType)) {             orderType = "desc";         }         return orderType;     }

如果,你觉得传入数据库中字段user_grade很不舒服的话。可以这样写SQL

SELECT  name , sex , age , user_grade as userGrade FROM user <if test="orderField != null" >     ORDER BY     <choose>         <when test="orderField == 'name'">             name ${orderType}         </when>         <when test="orderField == 'age'">             age ${orderType}         </when>         <when test="orderField == 'userGrade'">             user_grade ${orderType}         </when>         <otherwise>             create_time ${orderType}         </otherwise>     </choose> </if>

然后再传入字段时,就这样

user.setOrderField("userGrade");

Mybatis动态排序不生效问题

sql如下:

select * from  table_name order by #{field}

造成问题原因

mybatis动态参数

#{}方式传参数会使用preparedstatement预编译处理方式,参数是以?占位符的方式传递。可以看到mybaits的sql日志如下:

==> Preparing: SELECT * FROM table_name ORDER BY ? ==> Parameters: time(String)

preparedstatement预编译方式的参数替换的原理1可知预编译方式会对参数加上’'引号,生成的最终sql如下:

Mybatis如何实现基于动态参数的排序功能?

SELECT * FROM table_name ORDER BY 'time'

以上sql数据库不能正常解析 order by 后面的字段,这就是我们排序失效的原因

解决办法

将#{}参数方式改成${}参数方式即可。

原因: ${}参数的方式是简单的字符串替换。

在动态解析阶段,该 sql 语句会被解析成:

select * from table_name order by time

小结一下:

  • #{}方式传参数只能处理值参数 不能传递表名,字段等参数
  • ${}字符串替换,可以动态处理表名,字段参数,但是使用这种方式必须注意sql注入的风险,对参数做好校验处理

备注:preparedstatement具体实现原理见:com.mysql.jdbc.PreparedStatement中的setString方法源码

以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。