SpringBoot+MyBatis的动态SQL、使用动态SQL时List传值错误解决方案

[复制链接]
发表于 2023-2-6 19:42:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目录

实现动态SQL的四种方式:

1、XML配置

使用XML配置动态SQL,细节不表,详参:《MyBatis快速上手与知识点总结》 - 5.4 多条件查询 - 动态查询
2、脚本SQL



  • 使用注解实现,将XML文件的内容转换为注释即可
  • 当然,这种方式可读性差,且难以维护
  1. @Select("")  
  2. public List<User> findUserById(User user);  
复制代码
3、在方法中构建SQL



  • Dao层接口不写实现,次数使用内部类来生成动态SQL,并传入 @SelectProvider 注释
  • 增改删也有对应的 @InsertProvider、@UpdateProvider、@DeleteProvider 注释
  • 相比于脚本SQL更加清晰,比较直观,但是如果SQL过长的话,拼接会非常麻烦
  1. @Mapper
  2. public interface MybatisDao {
  3.     //使用UserDaoProvider类的findUserById方法来生成sql
  4.     @SelectProvider(type = UserDaoProvider.class, method = "findUserById")
  5.     public List<User> findUserById(User user);
  6.     class UserDaoProvider {
  7.         public String findUserById(User user) {
  8.             String sql = "SELECT * FROM user";
  9.             if(user.getId()!=null){
  10.                 sql += " where id = #{id}";
  11.             }
  12.             return sql;
  13.         }
  14.     }
  15. }
复制代码
4、结构化SQL



  • 这是把前面的内部类改造一下:

    • SELECT:表示要查询的字段,如果一行写不完,可以在第二行再写一个SELECT,这两个SELECT会智能的进行合并而不会重复
    • FROM 和 WHERE:跟SELECT一样,可以写多个参数,也可以在多行重复使用,最终会智能合并而不会报错。

  • 这样语句适用于写很长的SQL时,能够保证SQL结构清楚。便于维护,可读性高。
  • 但是这种自动生成的SQL和HIBERNATE一样,在实现一些复杂语句的SQL时会束手无策。所以需要根据现实场景,来考虑使用哪一种动态SQL
  • 上面的例子只是最基本的用法:更多详细用法,可以参考mybatis中文网的专门介绍:
    http://www.mybatis.org/mybatis-3/zh/statement-builders.html
  1. @Mapper
  2. public interface MybatisDao {
  3.     //使用UserDaoProvider类的findUserById方法来生成sql
  4.     @SelectProvider(type = UserDaoProvider.class, method = "findUserById")
  5.     public List<User> findUserById(User user);
  6.     public String findUserById(User user) {   
  7.         return new SQL(){{   
  8.             SELECT("id,name");   
  9.             SELECT("other");   
  10.             FROM("user");   
  11.             if(user.getId()!=null){   
  12.                 WHERE("id = #{id}");   
  13.             }   
  14.             if(user.getName()!=null){   
  15.                 WHERE("name = #{name}");   
  16.             }   
  17.             //从这个toString可以看出,其内部使用高效的StringBuilder实现SQL拼接   
  18.         }}.toString();   
  19.     }
  20. }
复制代码
关于动态SQL的List传值错误问题

动态SQL中,有时要对批量数据进行处理,难免会使用list做为参数
1、错误代码



  • 这是一个最简单的list传参,但是在运行时会报传参错误。
  • 这是mybatis内部机制造成的,其参数需要是key/value结构,当遇到这里不是 key/value结构的list时,mybatis会自己把它转换成key/value结构,key就是他的名字"list",value就是他的值 list 对象
  1. @SelectProvider(type = UserDaoProvider.class, method = "find")
  2. public List<Map> find(List list);   
  3. class UserDaoProvider {
  4.     public String find(List list) {
  5.     }
  6. }
复制代码
2、解决错误

要正确传参需要使用key/value结构的map,如下:
  1. @SelectProvider(type = UserDaoProvider.class, method = "find")
  2. public List<Map> find(List list);   
  3. class UserDaoProvider {
  4.     public String find(Map map) {
  5.         List list = (List) map.get("list");
  6.     }
  7. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表