企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] # 脚本sql XML配置方式的动态SQL我就不讲了,有兴趣可以自己了解,下面是用`<script>`的方式把它照搬过来,用注解来实现。适用于xml配置转换到注解配置 ~~~ @Select("<script>select * from user <if test=\"id !=null \">where id = #{id} </if></script>") public List<User> findUserById(User user); ~~~ 还可以这样 ~~~ @Update("<script> update users <set> <if test="userName != null">userName=#{userName},</if> <if test="nickName != null">nick_name=#{nickName},</if> </set> where id=#{id} </script>") void update(User user); ~~~ # 方法中构建sql dao接口中是不能写实现的,所以这里借用内部类来生成动态SQL。增改删也有对应的`@InsertProvider`、`@UpdateProvider`、`@DeleteProvider` * type:动态⽣成 SQL 的类 * method:类中具体的⽅法名 ~~~ @Mapper public interface MybatisDao { //使用UserDaoProvider类的findUserById方法来生成sql @SelectProvider(type = UserDaoProvider.class, method = "findUserById") public List<User> findUserById(User user); class UserDaoProvider { public String findUserById(User user) { String sql = "SELECT * FROM user"; if(user.getId()!=null){ sql += " where id = #{id}"; } return sql; } } ~~~ 这比`<script>`更加清晰,适用于查询语句不是很长、条件不多的场景,SQL很直观。但是在写很长的SQL时,这样拼接SQL同样会很痛苦 # 结构化SQL ~~~ public String findUserById(User user) { return new SQL(){{ SELECT("id,name"); SELECT("other"); FROM("user"); if(user.getId()!=null){ WHERE("id = #{id}"); } if(user.getName()!=null){ WHERE("name = #{name}"); } //从这个toString可以看出,其内部使用高效的StringBuilder实现SQL拼接 }}.toString(); } ~~~ 这是把前面的内部类改造一下 SELECT:表示要查询的字段,如果一行写不完,可以在第二行再写一个SELECT,这两个SELECT会智能的进行合并而不会重复 FROM和WHERE:跟SELECT一样,可以写多个参数,也可以在多行重复使用,最终会智能合并而不会报错 这样语句适用于写很长的SQL时,能够保证SQL结构清楚。便于维护,可读性高。但是这种自动生成的SQL和HIBERNATE一样,在实现一些复杂语句的SQL时会束手无策。所以需要根据现实场景,来考虑使用哪一种动态SQL 上面的例子只是最基本的用法:更多详细用法,可以参考mybatis中文网的专门介绍 http://www.mybatis.org/mybatis-3/zh/statement-builders.html # list传值错误 动态SQL中,有时要对批量数据进行处理,难免会使用list做为参数 ~~~ @SelectProvider(type = UserDaoProvider.class, method = "find") public List<Map> find(List list); class UserDaoProvider { public String find(List list) { ~~~ 这是一个最简单的list传参,但是在运行时会报传参错误。这是mybatis内部机制造成的,其参数需要是key/value结构,当遇到这里不是key/value结构的list时,mybatis会自己把它转换成key/value结构,key就是他的名字"list",value就是他的值List,要正确传参需要使用key/value结构的map,如下 ~~~ @SelectProvider(type = UserDaoProvider.class, method = "find") public List<Map> find(List list); class UserDaoProvider { public String find(Map map) { List list = (List) map.get("list"); ~~~