一、动态sql
1.1 sql片段
在书写sql语句的查询时,不推荐大家用’ * ‘号 建议大家把想要查询出来的列都写出。具体的写法如下:
(1)写sql标签 (2)在sql语句中引入sql片段
1.2 set标签
这个配合if标签一起用,一般在用于修改语句。如果传递的参数值为null,那么应该不用修改该列的值
set可以帮助我们生成关键字 set 并且可以去除最后的一个逗号
测试代码如下:我们传的一个参数为一个student实体类,里面的属性有name,age,cid和一个Class(自定义的)类的Class,我们只需要关系 我们要用到的name,age,cid即可
我们需要修改的值为name,age,cid 这些都不为空 那么动态sql语句就应该变成:
可以发现,set标签会自动帮我们去除最后cid处的逗号。
1.3 foreach标签
循环标签,可以帮助我们处理一些动态的批量任务,例如批量添加,批量查询,批量删除等等。我们可以传入一个数组或者一个list集合,然后通过foreach标签将集合内的条件一个一个的放入我们的sql语句从而实现动态的批量删除的处理效果.
foreach标签内的属性:
1.collection:类型 如果你使用的为数组array 如果你使用的为集合 那么就用list
2.item:数组中每个元素赋值的变量名
3.open:以谁开始
4.close:以谁结束
5.separator:分割符
用到的数据库的表如图。下面给大家举三个例子
(1).根据id批量查询学生信息
StudentDao:
StudentMapper:
<resultMap id="stuMap" type="com.wjk.entity.Student">
<id column="stu_id" property="id"/>
<result column="stu_name" property="name"/>
<result column="stu_age" property="age"/>
</resultMap>
<sql id="stu">
stu_id,stu_name,stu_age,cid
</sql>
<select id="selectByFor" resultType="com.wjk.entity.Student">
select * from student where stu_id in
<foreach collection="array" item="forEachIds" separator="," open="(" close=")">
#{forEachIds}
</foreach>
</select>
(2)根据id批量删除
StudentDao:
StudentMapper:
<delete id="deleteByFor">
delete from student where stu_id in
<foreach collection="array" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
(3) 批量添加学生信息
这里我们传入的参数可以换成集合类型----List<Student>集合。集合里面装的都是Student对象类型的数据。这样才能将要添加的学生的信息传入sql中
StudentDao:
StudentMapper:注意 我们想要调用list集合内的Student对象的属性,调用的写法应该为Xxx(item) xxx(属性名).同样紫定义对象类型的数组也应该这样调用属性
<insert id="insertByFor">
insert into student values
<foreach collection="list" item="stu" separator=",">
(null ,#{stu.name},#{stu.age},#{stu.cid})
</foreach>
</insert>
二、映射文件特殊字符的处理
在Mapper中写我们的SQL语句中,会遇到一些特殊字符,他会与哦我们的sql代码会产生冲突,例如我们sql中写这样的语句:
可以看到我们的小于号,就是一种特殊字符。那么我们应该如何处理这种问题?
有两种方法可以解决
第一种:使用转义符。java中有这些特殊字符的转义符
第二种:用<![CDATA[sql语句]]>方法 注意这种方法不能括住我们的标签 (例如include标签),我们可以在需要用到的地方使用这个方法,没必要在整个sql语句都套入在内
三、模糊查询
模糊查询的sql语句
select * from 表明 where 列名 like '%a%'
有两种方法可以实现这种拼接
(1) 使用字符串函数 完成拼接----- concat(这属于sql基础的知识点)
<select id="selectByLike" resultMap="stuMap">
select <include refid="stu"/>
from student where stu_name like '%${name}$'
</select>
(2)使用${}代替。这种方式实际上是字符串的拼接,它并不能防止sql注入问题 ,而我们之前用的#{}就相当于编译,可以防止sql注入问题。所有这种方式不推荐使用,所谓防君子不防小人
<select id="selectByLike" resultMap="stuMap">
select <include refid="stu"/> from student where stu_name like '%${name}%'
</select>
四、联表查询
例子:根据id查询学生信息并包括改学生所在班里的所有信息
需要用的表:我们需要从多的一方来查询一的一方。这里学生表就相当于多的一方,班级表就相当于一的一方
sql语句:
select * from tb_stu s join tb_class c on s.class_id=c.cid where stu_id= xxx
实现方式一:
首先在我们的Student实体类中(相当于多的一方)加入我们Class类型(一的一方)的属性
/**
* Created by Intellij IDEA
*
* @author 王俊凯
* @Date: 2022/6/5 12:39
* @Version 1.0
*/
package com.wjk.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private Integer id;
private String name;
private Integer age;
private Integer cid;
private Class aClass;//学生所属的班级
StudentDao:
StudentMapper:重点:resultMap标签内的association标签:表示一的一方。property:表示属性名(就是我们实体类中的Class属性)javaType:表示该属性名对应的数据类型
<resultMap id="all" type="com.wjk.entity.Student">
<id column="stu_id" property="id"/>
<result column="stu_name" property="name"/>
<result column="stu_age" property="age"/>
<result column="c_id" property="cid"/>
<association property="aClass" javaType="com.wjk.entity.Class">
<id column="cid" property="cid"/>
<result column="cname" property="cname"/>
</association>
</resultMap>
<sql id="allClass">
stu_id,stu_name,stu_age,s.cid c_id,c.cid,cname
</sql>
<select id="selectClassById" resultMap="all">
select <include refid="allClass"/>
from student s join class c on s.cid=c.cid where stu_id=#{id}
</select>
实现方式二:
map封装(不推荐这种方式)。用这种方式封装我们查询到的数据,就不需要改动我们的实体类,也不用关心其属性内的映射关系。
StudentDao:
StudentMapper:
<select id="selectClassById09" resultType="java.util.Map">
select <include refid="allClass"/>
from student s join class c on s.cid=c.cid where stu_id=#{id}
</select>
需要避免的问题:两个表的列名应该尽量避免相同,如果相同,需要起别名来区别。resultMap中的标签内的column属性应该与你起了别名后的列名相同。Map本身也是无序不重复的,我们的属性名也就是map中的key值也需要保证不能相同。
体会:使用mybatis我们需要做的事情就是处理好查询到的结果与返回值(一般是你得实体类或实体类组成的集合)的属性相对应(resultMap标签)。其他的内容与我们学习JDBC+Dao整合时大致相同。所以难点就在于将返回的内容处理好,其他的一些包括sql语句标签和动态sql标签都是帮助我们书写sql语句的,基础的sql部分的知识点需要掌握。框架的好处就是帮我们简化流程,不要把他想的很复杂。