SpringBoot动态SQL
目录
动态SQL【重点】
1、 SQL片段
2、if
3、where [重点]
4、 set
5、 foreach
动态SQL【重点】
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
自己话理解: 帮助我们拼接SQL
常见的动态SQL语法
SQL片段(官方不是在动态SQL章节)
where , if
set
foreach
trim
choose-when-otherwise
1、 SQL片段
这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用。
自己的话: 减少代码重复,主要用于抽取字段,表名等
<!-- 将重复的SQL代码抽取成SQL片段,以供复用 -->
<sql id="userField">
id,
username,
password,
phone,
create_time,
money,
sex
</sql>
<select id="findAll" resultType="User">
select
<!-- 引入片段 -->
<include refid="userField"/>
from
tb_user
</select>
2、if
if就是用来判断,主要用于判断要不要拼接对应的条件语句
-- 需求:查询用户,条件是money=1000,如果密码不为空,也根据密码查 select * from tb_user where money = 1000 select * from tb_user where money = 1000 and password= '123456'
UserMapper.java接口方法
public interface UserMapper {
/**
* 演示if动态sql
*/
List<User> findByMap(HashMap<String,Object> map);
}
UserMapper.xml
<select id="findByMap" resultMap="userResultMap">
<!-- #{}写map的key -->
select
<include refid="userFields"/>
from
tb_user
where
<!-- username是map的key -->
<if test="username != null and username != ''">
and username = #{username}
</if>
<if test="password != null and password != ''">
and password = #{password}
</if>
</select>
测试
@GetMapping("/map")
@ResponseBody
public R map(){
HashMap<String, Object> map = new HashMap<>( );
// map.put("password","123456");
// map.put("username","Uzi");
User user = userService.findByMap(map);
if (user != null) {
return R.ok(user);
}
return R.fail();
}
注意: 通过application.yml添加日志,显示sql. 通过打印的sql来判断是否拼接成功
3、where [重点]
如果说只有if,可能会出现这么一种情况
SELECT * FROM tb_user WHERE多出一个where关键词!!
所以我们需要一个智能的,有条件时帮我们拼接where关键词,没有条件查询时,不拼接where,并且去掉多余的and关键词,但是不会主动帮助拼接and
<select id="findUserByWhere" resultType="User">
select
<include refid="userField"/>
from
tb_user
<where>
<if test="username != null and username != ''">
and username = #{username}
</if>
<if test="password != null and password != ''">
and password = #{password}
</if>
</where>
</select>
所以一般会where和if一起用
4、 set
用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,
忽略其它不更新的列
。
UserMapper.java接口方法
public interface UserMapper {
int updateUser(User user);
}
UserMapper.xml
<!-- set完成动态更新 -->
<update id="updateUser">
update tb_user
<!-- set标签自动拼接SET关键词 -->
<set>
<!-- 会自动过滤最后一个, -->
<!-- 特别注意,因为判断条件是!=null,基本不可能为null,所以将基本类型变为包装类 -->
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="password != null and password != ''">
password = #{password},
</if>
<if test="phone != null">
phone = #{phone},
</if>
<if test="createTime != null">
create_time = #{createTime},
</if>
<if test="money != 0.0">
money = #{money},
</if>
</set>
where id = #{id}
</update>
测试
5、 foreach
场景: 批量删除
delete from tb_user where id in (1,2,3,...);String sql = "delete from tb_user where id in ("; int iMax = idsArr.length - 1;// 最大下标 for (int i = 0; i < idsArr.length; i++) { int id = idsArr[i]; sql += id; if (i != iMax) { sql += ","; } else { sql += ")"; } }
UserMapper.java
public interface UserMapper {
// 为了演示动态sql foreach
int deleteBatch(List<Integer> ids);
}
UserMapper.xml
<!-- 动态sql foreach -->
<delete id="deleteBatch">
delete from tb_user
where id in
<!--
<foreach>开始循环,取出集合中的数据
collection,要遍历的集合,此处必须写list
item , 遍历得到结果,命名任意,但是下面#{}内的名字要和这里一致
-->
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
测试
// 批量删除
@GetMapping("/delete/batch")
// http://localhost:8888/delete?id=1&id=2&id=3
public R deleteBatch(@RequestParam List<Integer> list){
int i = userService.deleteBatch(list);
if (i > 0) {
return R.ok(i);
}
return R.fail();
}