动态sql是Mybatis的强大功能之一,能够完成不同条件下不同的sql拼接。
标签
如图是gitee上创建仓库的页面:
可以分为两种字段,必填字段和非必填字段,在创建仓库时无法确定用户是否会传入”仓库介绍“字段,如果用户不填写,那么前端传过来的就是Null, 在sql中""和null是不相等的
,因此需要使用标签来判断。
语法格式:
…
- 中的test会产生一个boolean类型的结果,如果为true,那么执行if标签的内容;如果为false,那么不执行if里面的内容。
- test中的参数,是传入对象的属性,不是数据库字段
咱们这里使用的数据表和前几篇一致,为articleinfo和userinfo表
需求:在用户注册环节,photo字段非必填。
photo字段可以标签,当photo字段不为空,则添加;为空就不添加。并且要注意 , 放的位置,不能跟着password后面,因为如果photo字段为空,就会造成sql语法错误
int addUser(Userinfo userinfo);
<insert id="addUser">insert into userinfo (username, password<if test="photo!=null">, photo</if>)values (#{username}, #{password}<if test="photo!=null">, #{photo}</if>)</insert>
@Testvoid addUser() {Userinfo userinfo = new Userinfo();userinfo.setUsername("张三");userinfo.setPassword("2345");userinfo.setPhoto(null); //在sql中”“不等于NulluserMapper.addUser(userinfo);System.out.println(userinfo);}
标签
在用户注册的时候,只有一个photo字段是非必填项,如果所有字段都是非必填项,可以考虑使用标签结合标签,对多个字段都采取动态生成的方式。
标签中有如下属性:
- prefix: 表示整个语句块,以prefix的值作为前缀
- suffix: 表示整个语句块,以suffix为值作为后缀
- prefixOverrides: 表示整个语句块要去除掉的前缀
- suffixOverrides: 表示整个语句块要去除掉的后缀
int addUser2(Userinfo userinfo);
<insert id="addUser2" useGeneratedKeys="true" keyColumn="id">insert into userinfo<trim prefix="(" suffix=")" suffixOverrides=","><if test="username != null">username,</if><if test="password != null">password,</if><if test="photo != null">photo,</if></trim>values<trim prefix="(" suffix=")" suffixOverrides=","><if test="username != null">#{username},</if><if test="password != null">#{password},</if><if test="photo != null">#{photo},</if></trim></insert>
@Testvoid addUser2() {Userinfo userinfo = new Userinfo();userinfo.setUsername("王五");userinfo.setPassword("45667");userinfo.setPhoto(null);userMapper.addUser2(userinfo);System.out.println(userinfo);}
在上面的sql动态解析时,会将第一个做如下处理:
- 基于
prefix
,开始部分加上(
- 基于
suffix
,结束部分加上)
- 多个组织的语句都以
,
结尾,在最后拼接好的字符串是以,
结尾,会基于suffixOverrides
去掉最后一个,
标签
顾名思义和mysql中的where作用一样,都是用来条件查询。
需求:跟据前端提供的用户名和密码(都是非必传的参数)查询用户信息
List<Userinfo> selectByParam(@Param("username") String username, @Param("password") String password);
<select id="selectByParam" resultType="com.example.demo.entity.Userinfo">select * from userinfo<where><if test="username != null">username = #{username}</if><if test="password != null">and password = #{password}</if></where></select>
@Testvoid selectByParam() {List<Userinfo> list = userMapper.selectByParam(null, "admin");System.out.println(list);}
- where标签通常需要配合if标签一起使用
- where标签会删除最前面的and关键字(所以上面的例子中就把password前面的and关键字去除)
- where标签如果里面没有内容,那么他不会生成where sql语句
标签
顾名思义和mysql的set作用一样,都是用来更新数据。
需求:前端传递Userinfo给后端(部分属性是非必填),请根据id修改用户信息
int update(Userinfo userinfo);
<update id="update">update userinfo<set><if test="username != null">username = #{username},</if><if test="password != null">password = #{password},</if><if test="photo != null">photo = #{photo}</if></set>where id = #{id}</update>
@Testvoid update() {Userinfo userinfo = new Userinfo();userinfo.setUsername("张三");userinfo.setPassword(null);userinfo.setPhoto("bbb.png");userinfo.setId(1);userMapper.update(userinfo);System.out.println(userinfo);}
- set标签通常配合 if 标签一起使用
- set标签会自动去除最后一个逗号
标签
顾名思义用来循环遍历的,标签有如下属性:
- collection: 绑定方法参数中的集合,如List,Set,Map
- item: 遍历时的对象
- open:语句块开头的字符串
- close: 语句块结束的字符串
- separator: 每次遍历之间间隔的字符串
需求:根据多个文章id删除文章数据
int dels(List<Integer> list);
<delete id="dels">delete from userinfowhere id in<foreach collection="list" item="item" open="(" close=")" separator=",">#{item}</foreach></delete>
@Testvoid dels() {List<Integer> list = new ArrayList<>();list.add(1);list.add(3);int dels = userMapper.dels(list);Assertions.assertEquals(2, dels);}