复杂情况:动态SQL使用🍭
动态 SQL 是Mybatis的强大特性之⼀,能够完成不同条件下不同的 SQL 拼接。 可以参考官方文档:mybatis – MyBatis 3 | 动态 SQL
一、< if>标签🍭
在注册用户的时候,可能会有这样⼀个问题,有的信息是必填,有的是选填,那如果在添加⽤户的时候有不确定的字段传入,程序应该 如何实现呢?
这个时候就需要使用动态标签 < if> 来判断了,比如添加的时候性别 sex 为非必填字段,具体实现如下:
<insert id="insert"> insert into user( username, password, <if test="sex != null"> sex, if> birthday, head ) values ( #{username}, #{password}, <if test="sex != null"> #{sex}, if> #{birthday}, #{head} ) insert>
需要注意 test 中的 sex,是传入对象中的属性,不是数据库字段。而且if标签都是成对出现的
二、< trim>标签🍭
之前的插入用户功能,只是有⼀个 sex 字段可能是选填项,如果所有字段都是非必填项,就考虑使用< trim>标签结合< if>标签,对多个字段都采取动态生成的方式。
< trim>标签中有如下属性:
- prefix:表示整个语句块,以prefix的值作为前缀
- suffix:表示整个语句块,以suffix的值作为后缀
- prefixOverrides:表示整个语句块要去除掉的前缀
- suffixOverrides:表示整个语句块要去除掉的后缀
调整 UserMapper.xml 的插入语句为:
<insert id="insert"> insert into user <trim prefix="(" suffix=")" suffixOverrides=","> <if test="username != null"> username, if> <if test="password != null"> password, if> <if test="sex != null"> sex, if> <if test="birthday != null"> birthday, if> <if test="head != null"> head, if> <if test="createTime != null"> create_time, if> trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="username != null"> #{username}, if> <if test="password != null"> #{password}, if> <if test="sex != null"> #{sex}, if> <if test="birthday != null"> #{birthday}, if> <if test="head != null"> #{head}, if> <if test="createTime != null"> #{createTime}, if> trim> insert>
在以上 sql 动态解析时,会将第⼀个
- 基于 prefix 配置,前缀部分加上 (
- 基于 suffix 配置,后缀部分加上 )
- 多个 < if>组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于 suffixO verrides 配置去掉最后⼀个 ,
- 注意 < if test=“createTime != null”> 中的 createTime 是传入对象的属性,不是数据库字段
三、标签🍭
传入的用户对象,根据属性做 where 条件查询,用户对象中属性不为 null 的,都为查询条件。如user.username 为 "a",则查询条件为 where username="a":
UserMapper:
List selectByCondition(User user);
UserMapper.xml:
<select id="selectByCondition" parameterType="com.example.ssmdemo1.entity.Userinfo" resultMap="baseMap"> select id, username, password, nickname, sex, birthday, head, create_time from user <where> <if test="username != null"> and username=#{username} if> <if test="password != null"> and password=#{password} if> <if test="sex != null"> and sex=#{sex} if> <if test="birthday != null"> and birthday=#{birthday} if> <if test="head != null"> and head=#{head} if> <if test="createTime != null"> and create_time=#{createTime} if> where> select>
以上标签也可以使用 替换,中间的if标签代码不需要变。
四、标签🍭
根据传入的用户对象属性来更新用户数据,可以使用标签来指定动态内容。
UserMapper 接口中修改用户方法:根据传入的用户 id 属性,修改其他不为 null 的属性:
int updateById(User user);
UserMapper.xml 中添加更新用户 SQL:
<update id="updateById" parameterType="com.example.ssmdemo1.entity.Userinfo"> update user <set> <if test="username != null"> username=#{username}, if> <if test="password != null"> password=#{password}, if> <if test="sex != null"> sex=#{sex}, if> <if test="birthday != null"> birthday=#{birthday}, if> <if test="head != null"> head=#{head}, if> <if test="createTime != null"> create_time=#{createTime}, if> set> where id=#{id} update>
以上标签也可以使用 替换。
五、标签🍭
对集合进⾏遍历时可以使用该标签。标签有如下属性:
- collection:绑定方法参数中的集合,如 List,Set,Map或数组对象
- item:遍历时的每⼀个对象
- open:语句块开头的字符串
- close:语句块结束的字符串
- separator:每次遍历之间间隔的字符串
示例:根据多个文章 id 来删除文章数据。
ArticleMapper 中新增接口方法:
int deleteByIds(List ids);
ArticleMapper.xml 中新增删除 SQL:
<delete id="deleteByIds"> delete from article where id in <foreach collection="list" item="item" open="(" close=")" separator=","> #{item} foreach> delete>
单元测试代码,删除id为5和6的用户:
@Test void deleteByIds() { List ids=new ArrayList<>(); ids.add(5); ids.add(6); int result=userMapper.deleteByIds(ids); System.out.println("删除:"+result); }
六、choose-when-otherwise🍭
类似于Java中的switch语句,根据不同条件选择不同的SQL片段。
<select id="getUserList" resultType="User"> SELECT * FROM users <where> <choose> <when test="status != null"> AND status = #{status} when> <when test="name != null and name != ''"> AND name = #{name} when> <otherwise> AND active = 1 otherwise> choose> where> select>
动态SQL是MyBatis的一个重要特性,它允许你在SQL语句中根据条件动态地添加、修改或删除语句片段,以便更灵活地构建SQL查询和更新操作。
上面这些示例只是MyBatis动态SQL的一小部分用法。你可以根据自己的需求和情况,结合使用这些特性来构建更灵活、可维护的数据库操作语句。记得阅读MyBatis的官方文档以深入了解动态SQL的更多用法和细节。