MyBatis的强大特性之一便是它的动态SQL,这里主要说下<if>,<choose>,<where>,<set>,<foreach>,<bind>。搭建mybatis(基于springBoot)和增删改查,见上文
一、if
<select id="selectByUser" resultType="com.lbc.mybatisDemo.book.model.SysUser"> select * from sys_user where 1=1 <if test="userName !=null and userName !=''"> and user_name like concat('%',#{userName},'%') </if> <if test="userEmail !=null and userEmail !=''"> and user_email like concat('%',#{userEmail},'%') </if> </select>if标签里的test是必填属性,该值应该是一个符合OGNL规范的判断表达式,该表达式返回的应该是true 或 false,除此之外所有的非0值均为true,只有0值为false。
判断条件property != null and property !=' ' 适用于任何object对象,而 property !=' ' 或 property == ' '只适应于String类型的字段。
SysUser sysUser = new SysUser(); sysUser.setUserName("my"); List<SysUser> query = userMapper.selectByUser(sysUser); System.out.println(query);insert、update同理使用。
二、choose
通过if标签的学习,我们也意识到了,好像if中并没有if···else···这种类型的判断,而在实际的开发中难免会遇到条件判断的情况,那choose的出现便弥补了这个缺陷,choose标签中含有<when>、<otherwise>两个标签,一个choose应该至少含有一个when标签。
<select id="selectByIdOrUserName" resultType="com.lbc.mybatisDemo.book.model.SysUser"> select * from sys_user where 1=1 <choose> <when test="id != null"> and id = #{id} </when> <when test="userName !=null and userName !=''"> and user_name like concat('%',#{userName},'%') </when> <otherwise> and 1 = 2 </otherwise> </choose> </select>这是一个判断是否有id或userName属性的语句,要是两者全为空,则返回一个and 1=2(错误条件,导致选出的结果为空)
SysUser sysUser = new SysUser(); sysUser.setUserName("my"); List<SysUser> query = userMapper.selectByIdOrUserName(sysUser); System.out.println(query);三、where
<select id="selectByUserWhere" resultType="com.tiza.mybatisDemo.book.model.SysUser"> select * from sys_user <where> <if test="userName !=null and userName !=''"> and user_name like concat('%',#{userName},'%') </if> <if test="userEmail !=null and userEmail !=''"> and user_email like concat('%',#{userEmail},'%') </if> </where> </select>从中很容易看出,之前的where 1= 1 主要是为了防止if的所有语句都不适用,就会导致 select * from sys_user where 这样where没有条件,就会导致sql语句出错。有些开发人员不喜欢用1=1这种形式,那就可以直接用<where>标签,当<where>中的所有条件都不满足时,where也就随之不存在了。
四、set
<update id="updateByIdSelective"> update sys_user <set> <if test="userName !=null and userName !=''"> user_name= #{userName}, </if> <if test="userPassword !=null and userPassword !=''"> user_password=#{userPassword}, </if> <if test="userEmail !=null and userEmail !=''"> user_email=#{userEmail}, </if> <if test="userInfo !=null and userInfo !=''"> user_info=#{userInfo}, </if> <if test="headImg !=null and headImg !=''"> head_img = #{headImg,jdbcType = BLOB}, </if> <if test="createTime !=null and createTime !=''"> create_time =#{createTime,jdbcType =TIMESTAMP} </if> </set> where id = #{id} </update>set是将set值放在标签内,类似上文的where,用法也相似。
五、foreach
foreach是循环的语句,在mybatis中是一种集合的条件属性
<select id="selectByIdList" resultType="com.lbc.mybatisDemo.book.model.SysUser"> select * from sys_user where id in <foreach collection="list" open="(" close=")" separator="," item="id" index="i"> #{id} </foreach> </select>foreach包含以下属性
collection:必填 值为要迭代循环的属性名。
item:变量名,值为从迭代对象中取的每一个值。
index:索引的属性名,在集合数组情况下值为当前索引值,当迭代循环的对象是Map类型时,这个值为Map的Key
open:整个循环内容开头的字符串。
close:整个循环内容结束的字符串。
separator:每次循环的分隔符。
collection对象中可以是集合list也可以是map对象
1、只有一个数组参数或集合参数时
DefaultSqlSession中wrapCollection方法如下:
private Object wrapCollection(Object object) { DefaultSqlSession.StrictMap map; if (object instanceof Collection) { map = new DefaultSqlSession.StrictMap(); map.put("collection", object); if (object instanceof List) { map.put("list", object); } return map; } else if (object != null && object.getClass().isArray()) { map = new DefaultSqlSession.StrictMap(); map.put("array", object); return map; } else { return object; } }当参数为collection集合时,默认会转为一个key为collection的Map,若参数为list集合时,那么map的可以就为“list”(foreach标签中的collection = "list" 就可以得到这个list集合),当参数为数组时,也会转换为map,默认的key则会变成array。
注:使用@Param时指定名称,则collection要对应修改该名称。
List<SysUser> selectByIdList(List<Long> idArray); List<SysUser> selectByIdList(@Param("custom") List<Long> idArray);2、有多个参数时
@Param应该给每一个参数指定一个名称用于区分
3、参数为map时
使用map参数与@Param类似,要指定名称给collection,否则找不到对应的value,如不指定名称,默认的名称为_parameter。
4、参数为对象时
这种情况要指定对象的属性名,对象内多层嵌套的对象,要用属性.属性(集合和数组可以使用下标值),从而指定深层的属性值。
foreach中的批量插入
<insert id="insertList" > insert into sys_user (user_name,user_password,user_email,user_info,head_img,create_time) value <foreach collection="list" item="user" separator=","> (#{user.userName},#{user.userPassword},#{user.userEmail},#{user.userInfo},#{user.headImg,jdbcType = BLOB},#{user.createTime,jdbcType =TIMESTAMP}) </foreach> </insert>int insertList(List<SysUser> sysUsers);
List<SysUser> userList = new ArrayList<SysUser>(); for (int i = 0; i < 3; i++) { SysUser user1 = new SysUser(); user1.setUserName("Test"+i); user1.setUserPassword("123456"); user1.setUserEmail("1233@123.com"); userList.add(user1); } int row = userMapper.insertList(userList); System.out.println(row);foreach实现动态update
<update id="updateByMap"> update sys_user set <foreach collection="_parameter" item="val" index="key" separator=","> ${key} = #{val} </foreach> where id = #{id} </update>其中:
#{}这种方式SQL语句是经过预编译的
${}在动态解析时候,会传入参数字符串