Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题。
当遇到多个查询条件,使用where 1=1 可以很方便的解决我们的问题,但是这样很可能会造成非常大的性能损失,因为添加了 “where 1=1 ”的过滤条件之后,数据库系统就无法使用索引等查询优化策略,数据库系统将会被迫对每行数据进行扫描(即全表扫描) 来比较此行是否满足过滤条件,当表中的数据量较大时查询速度会非常慢;此外,还会存在SQL 注入的风险。
有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。
AND u.is_update = #{isUpdate, jdbcType=INTEGER}
AND u.is_delete = #{isDelete, jdbcType=INTEGER}
假设接口中传递的list如下所示:
List list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
其中foreach标签配置如下
insert into t_emp values
(null, #{emp.empName}, #{emp.age}, #{emp.sex}, #{emp.email}, null)
(#{item})
最终的结果为
('zhangsan'),('lisi'),('wangwu')
如果在foreach标签前面加上insert into table values,将会变形成
INSERT INTO user(user_name) VALUES('zhangsan'),('lisi'),('wangwu')
mybatis中sql标签与include标签进行配合,灵活的查询需要的数据。抽取可重用的sql片段放include,方便后面引用
STATUS IN (1,2,3,4)
采用${}
取参数时,include
标签的property
属性的优先级要高于外围mapper
的参数;
WHERE my.id = ${testVal}
-- 执行结果:select my.* FROM sys_user my WHERE my.id = 1
${abc},username,password
-- 执行结果:select id,username,password from t_user
-- 执行结果 select my.* FROM sys_user my WHERE my.id = 1
/* 执行结果
select my.* FROM sys_user my
LEFT JOIN sys_department dep ON my.department_id = dep.id
WHERE dep.id = 1
*/
WHERE ${fieldPrefix}id = 1
WHERE my.id = ${fieldPrefix}
调用
一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“values(“ 等前缀,或者添加“)“等后缀,可用于选择性插入、更新、删除或者条件查询等操作。
select * from user_tab where last_name=#{lastName} and age=#{age} and phone=#{phone}
使用示例
select * from user_tab where and age = ? and phone = ?
在动态sql的查询过程中,如果 lastName为null,所以第一个if不成立,里面的SQL语句不拼接,第二个if里面的and边紧跟在where后面了,语法错误。为了解决这个问题,只要加上prefixOverride即可,表示把动态生成的sql中,trim标签内的首个“and”去掉。
update user_tab set ast_name=?, age=?,
若phone的值为null,则会导致生成的sql语句最后一个符号为“,”,导致生成的sql出错。 为了避免此种情况,可使用trim标签中的suffixOverrides 将最后面的一个符号覆盖掉。
update user_tab
set
last_name=#{lastName},
age=#{age},
phone=#{phone}
resultType="java.lang.Integer"
将列名作为键,将查询出来的数据结果作为值。大概的应用场景是不知道查询的结果有多少字段或者不清楚字段名称。
多条记录
一条记录
还有一种使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功,这种不描叙了。
当 MyBatis 执行完一条更新语句后,会返回一个整数,返回值为受影响的数据库记录的行。update标签没有resultType属性
update UserInfo set name = #{name}
可以动态更新需要更新的列,忽略其它不更新的列,例:
update user_info
userName=#{userName},
userSex=#{userSex}
where id=#{keyId}
在 UserInfoMapper 接口中增加一个 updateUserInfo() 方法,代码如下。
int updateUserInfo(String name);
delete 标签用于定义 delete 语句,执行删除操作。当 MyBatis 执行完一条更新语句后,会返回一个整数,表示受影响的数据库记录的行数。