各位大佬光临寒舍,希望各位能赏脸给个三连,谢谢各位大佬了!!!
目录
1.问题的引出
我们在使用MyBatis的时候可能会产生这样一个疑问。如果我们想要插入的参数(当然不仅仅是插入),达不到原SQL语句的要求我们输入的参数数量怎么办。如:
insert into mybatis(user_name,password,age,gender,phone)
values(#{username},#{password},#{age},#{gender},#{phone});
但是这时候我们只想输入username,password和age。如果直接只输入这三个就会报错
如果把gender和phone设置为null,则结果又和预期不同(想要默认值但是数据库显示为null或者根本不能改为null值)
这时候就需要动态SQL来帮我们解决类似的问题。
2.动态SQL
动态SQL主要是引入了if,trim,where,set,foreach这五个标签来解决参数数量不对应的问题,我们先讲XML的实现方法,注解方法非常难用,我会在后面带过,原理都差不多。那让我们在几个案例中了解这几个标签吧!
案例一
使用insert语句任意插入username,password,age,gender,phone这几个字段
在这里我们使用if标签,和普通SQL语句一样,我们要先创建方法和insert标签:
<insert id="insertDP">
</insert>
这时候我们把标签里的内容加上if标签,这个标签和Java中的if逻辑上是一样的,都是判断,我们这里只需要判断Java中类的这个属性是否为null即可。方法比较复杂要一条一条判断,代码如下:
<insert id="insert">
insert into mybatis(user_name,password,age,gender,phone)
values(#{username},#{password},#{age},#{gender},#{phone})
</insert>
<insert id="insertDP">
insert into mybatis(
<if test="username!=null">
user_name
</if>
<if test="password!=null">
,password
</if>
<if test="age!=null">
,age
</if>
<if test="gender!=null">
,gender
</if>
<if test="phone!=null">
,phone
</if>
)
values(
<if test="username!=null">
#{username}
</if>
<if test="password!=null">
,#{password}
</if>
<if test="age!=null">
,#{age}
</if>
<if test="gender!=null">
,#{gender}
</if>
<if test="phone!=null">
,#{phone}
</if>
)
</insert>
接下来我们测试一下不设置age,测试代码如下:
@Test
void testSelectDP() {
StudentInfo studentInfo=new StudentInfo();
studentInfo.setUsername("laoba");
studentInfo.setPassword("123321");
studentInfo.setPhone("123321");
studentInfoDao2.insertDP(studentInfo);
}
可以看到我们的代码执行成功了 。
但是这时候有个问题,如果我们没有输入username那么语句就会多一个逗号,导致badSQL,原因也很简单,大家看看上述代码逻辑肯定就懂了。
那么如何解决呢,我们可以使用trim标签,这个标签可以给字符串去除前面和后面的指定字符,还能指定增加前面和后面的指定字符。代码如下:
</insert>
<insert id="insertDP">
insert into mybatis
<trim prefix="(" prefixOverrides="," suffix=")">
<if test="username!=null">
user_name
</if>
<if test="password!=null">
,password
</if>
<if test="age!=null">
,age
</if>
<if test="gender!=null">
,gender
</if>
<if test="phone!=null">
,phone
</if>
</trim>
<trim prefix="values(" suffix=")" prefixOverrides="," >
<if test="username!=null">
#{username}
</if>
<if test="password!=null">
,#{password}
</if>
<if test="age!=null">
,#{age}
</if>
<if test="gender!=null">
,#{gender}
</if>
<if test="phone!=null">
,#{phone}
</if>
</trim>
</insert>
不出所料我们不用名字也把这条数据添加进数据库了。
案例二
使用查询语句任意查询username,password,age这几个字段
在这里我们可以像上面一样用if标签来解决:
<select id="selectDP" resultMap="StudentMap">
select * from mybatis
<trim prefix="where" suffixOverrides="and">
<if test="username!=null">
user_name=#{username} and
</if>
<if test="id!=null">
id=#{id} and
</if>
<if test="age!=null">
age=#{age}
</if>
</trim>
</select>
但是这时候我们会发现,如果我们没有筛选条件就会多出一个where,这时候有三种解决办法。
用if标签
用if标签判断内容是否全为空,这个方法需要判断所有条件是否都不存在,比较麻烦。所以我们就引入了第二种方法,和if标签功能一样。
用where标签
where标签会自动在没有内容的时候取消where关键字,并且where标签会总动去除末尾and,也会在前面自动加where,是专门服务于where关键字的:
<select id="selectDP" resultMap="StudentMap">
select * from mybatis
<where>
<if test="username!=null">
user_name=#{username} and
</if>
<if test="id!=null">
id=#{id} and
</if>
<if test="age!=null">
age=#{age}
</if>
</where>
</select>
使用where 1=1
这个where 1=1的方法是程序员想出来的,这样就算没有任何条件也可以执行sql语句.因为1=1是恒成立的:
<select id="selectDP" resultMap="StudentMap">
select * from mybatis
where 1=1
<if test="username!=null">
user_name=#{username} and
</if>
<if test="id!=null">
id=#{id} and
</if>
<if test="age!=null">
age=#{age}
</if>
</select>
案例三
使用更新语句任意更新username,age这几个字段
还是一样,我们可以用if标签和trim标签来解决,和上面一样,这里我就不再多赘述了 ,我们这里了解一下update标签即可,它会自动加一个set,并且去除句首或句尾的逗号:
<update id="updateDP">
update mybatis
<set>
<if test="username!=null">
user_name=#{username} ,
</if>
<if test="age!=null">
age=#{age}
</if>
</set>
where id=#{id}
</update>
@Test
void updateDP() {
StudentInfo studentInfo=new StudentInfo();
studentInfo.setId(7);
studentInfo.setAge(1);
studentInfo.setUsername("333");
studentInfoDao2.updateDP(studentInfo);
}
案例四
搜索一个集合对应的所有的id
这里我们需要使用foreach标签:
<select id="selectList" resultType="com.mybatis.demomybatis.demos.model.StudentInfo">
select * from mybatis
where id in
<foreach collection="list" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</select>
这里的conllection表示集合的名字也可以直接输入collection(只有一个集合),open表示开头,close表示结尾,它们都是添加字符的属性,item是给集合元素命个名,可以下面使用。
我们测试一下试试:
@Test
void selectList() {
List<Integer> ids= Arrays.asList(6, 7);
System.out.println(studentInfoDao2.selectList(ids));
}
小结
我们算是把常用的标签讲完了,事实上还有两个标签sql和include,我在这直接一笔带过好了。sql就相当于把代码片段模板化,可以用include提取。就比如酱紫:
<sql id="select">
select * from mybatis
</sql>
<select id="selectTestInclude" resultType="com.mybatis.demomybatis.demos.model.StudentInfo">
<include refid="select"></include>
</select>
我们在第四行的select语句中就可以直接使用include来使用sql写好的模板(通过id调用)。
我们测试一下试试:
可以看到程序成功运行成功了。
总结
MyBatis的动态SQL像是JavaScript语言,但是我们还是很容易去理解的,毕竟计算机语言逻辑是互通的。动态SQL在日常开发中还是经常遇到的,所以我们程序猿要好好掌握呀!如果想偷懒建议大家去了解一下MybatisGenerator工具,可以自动生成sql的XML文件。那我们今天的学习旅程就到这啦,咱们下期再见!!!
制作不易,望各位大佬赏个脸,给个三连吧!!谢谢各位大佬了!!!