目录
返回类型
resultType
resultMap
1、字段映射
2、多表查询
动态SQL
if标签
where标签
set标签
choose(when,otherwise) 语句
trim标签
for-each标签
SQL片段
返回类型
resultType
Mybatis在查询时,一定要指定返回类型;而其他操作,默认返回修改数目
在正常情况下,我们查询使用resultType返回查询结果是可以的

但是,也有其他情况是resultType不能解决的
如果说,类和数据库的参数不匹配,那么查询出来的结果在填充到类对象时,就会找不到对应的字段,(数据库的结果根据数据库列名和类字段名称进行匹配赋值)
数据库的列名是class_id,而类字段是 stu_class,mybatis不能将这两个联系起来,这时就需要使用resultMap
resultMap
1、数据库列名和类字段名称不匹配,可以使用resultMap来配置映射关系
2、resultMap可以用来处理多表联查
1、字段映射
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectById">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->
    <resultMap id="Map" type="com.example.demo.Model.Student">
<!--        id标识这个resultMap,可以和数据库查找时id绑定,引用这个resultMap-->
<!--        type表示resultMap映射到的实体类-->
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="class_id" property="stu_class"></result>
<!--        id标识主键的映射 -->
<!--        result标识其他字段的映射-->
<!--        column表示数据库的字段,property表示类的字段,将数据库的列名和类字段联系起来-->
    </resultMap>
    <select id="selectById" resultMap="Map">
        <!--        这个id,表示实现StudentMapper接口的哪一个方法-->
        <!--        resultMap 表示方法的返回类型,使用id绑定到上述的resultMap-->
        select * from student where id=#{id}
        <!--        这里写具体的执行语句-->
    </select>
</mapper> 
这时,我们来运行单元测试:

2、多表查询
一个学生属于一个班级,一对一


1、创建Class类,Student类增加Class类的变量
@Data
public class Class {
    private Integer class_id;
    private String class_name;
} 
@Data
public class Student {
    private Integer id;
    private String name;
    private Integer class_id;
    private Class stu_class;
} 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectAll">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->
<!--    Class类的映射-->
<resultMap id="classMap" type="com.example.demo.Model.Class">
    <result column="class_id" property="class_id"></result>
    <result column="class_name" property="class_name"></result>
</resultMap>
    <resultMap id="StudentMap" type="com.example.demo.Model.Student">
        <!--        id标识这个resultMap,可以和数据库查找时id绑定,引用这个resultMap-->
        <!--        type表示resultMap映射到的实体类-->
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="class_id" property="class_id"></result>
        <!--        id标识主键的映射 -->
        <!--        result标识其他字段的映射-->
        <!--        column表示数据库的字段,property表示类的字段,将数据库的列名和类字段联系起来-->
<!--        association实现一对一多表查询的映射关系 -->
<!--        id 表示Student类中创建的Class对象的变量名称,resultMap表示class类的映射关系,会将查询到的Class数据按照此形式填充
            columnPrefix给数据库起别名,这样可以避免两个表有重名列时,数据重复的情况(第二个表id应该是2,第一个表id为1,因为同名,第二个表的id就变成了第一个表id的值 查询错误) -->
        <association property="stu_class" resultMap="classMap" columnPrefix="c_">
        </association>
    </resultMap>
    <select id="selectAll" resultMap="StudentMap">
        <!--        这个id,表示实现StudentMapper接口的哪一个方法-->
        <!--        resultMap 表示方法的返回类型,使用id绑定到上述的resultMap-->
<!--        class表的属性重命名-->
        select student.*,class.class_id c_class_id,class.class_name c_class_name from student,class where student.class_id=#{class_id} and class.class_id=#{class_id}
        <!--        这里写具体的执行语句-->
    </select>
</mapper> 

一个班级可以有多个学生 一对多
@Data
public class Student {
    private Integer id;
    private String name;
    private Integer class_id;
} 
@Data
public class Class {
    private Integer class_id;
    private String class_name;
    private List<Student> list;
} 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectAllStudents">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->
    <resultMap id="StudentMap" type="com.example.demo.Model.Student">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="class_id" property="class_id"></result>
    </resultMap>
    <!--    Class类的映射-->
    <resultMap id="classMap" type="com.example.demo.Model.Class">
        <result column="class_id" property="class_id"></result>
        <result column="class_name" property="class_name"></result>
        <collection property="list" resultMap="StudentMap" columnPrefix="s_"></collection>
        <!-- property 绑定字段  将student表以s_重命名-->
    </resultMap>
    <select id="selectAllStudents" resultMap="classMap">
        select class.*, student.id s_id,student.name s_name,student.class_id s_class_id from class,student where student.class_id=#{class_id} and class.class_id=#{class_id}
        <!--        这里写具体的执行语句-->
    </select>
</mapper> 

动态SQL
如果有比较复杂的业务,我们需要写复杂的 SQL 语句,往往需要拼接,而拼接 SQL ,稍微不注意,由于引号,空格等缺失可能都会导致错误。
那么怎么去解决这个问题呢?这就要使用 mybatis 动态SQL,通过 if, choose, when, otherwise, trim, where, set, foreach等标签,可组合成非常灵活的SQL语句,从而在提高 SQL 语句的准确性的同时,也大大提高了开发人员的效率。
if标签
根据name和class_id来查询学生信息
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectStudent">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->
    <select id="selectStudent" resultType="com.example.demo.Model.Student">
       select * from student where name=#{name} and class_id=#{class_id}
    </select>
</mapper> 

如果class_id为空,那么就是select * from student where name=#{name} and class_id=null;
如果name为空,那么就是select * from student where name= and class_id=#{class_id};这是错误的写法,我们这时就要用到if标签
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectStudent">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->
    <select id="selectStudent" resultType="com.example.demo.Model.Student">
       select * from student where
        <if test="name!=null">
            name=#{name}
        </if>
        <if test="class_id!=null">
            and class_id=#{class_id}
        </if>
    </select>
</mapper> 
如果class_id为空,那么就是select * from student where name= #{name};
如果name为空,那么就是select * from student where and class_id=#{class_id};这是错误的写法,要使用到where标签

where标签
where标签就是为sql加上where关键字,且会自动的多余的and、or关键字,当所有的条件都不成立的时候,where标签也不会生成
去掉前面的and,不会去掉后面的and
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectStudent">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->
    <select id="selectStudent" resultType="com.example.demo.Model.Student">
       select * from student
        <where>
        <if test="name!=null">
            name=#{name}
        </if>
        <if test="class_id!=null">
            and class_id=#{class_id}
        </if>
        </where>
    </select>
</mapper> 

set标签
set元素会动态前置SET关键字,同时也会自动抹去where查询条件前多余的逗号,避免因为使用条件语句在生成赋值语句的后面留下不需要的逗号
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.UpdateStudent">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->
    <update id="updateStudent" >
   update student
        <set>
            <if test="id!=null">
                id=#{id}
            </if>
            <if test="name!=null">
                 ,name=#{name}
            </if>
        </set>
    </update>
</mapper> 

choose(when,otherwise) 语句
有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectByChoices">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->
    <select id="selectByChoices" resultType="com.example.demo.Model.Student">
        select * from student where
   <choose>
       <when test= "id!=null">id=#{id}</when>
       <when test="name!=null">name=#{name}</when>
       <otherwise > class_id=#{class_id}</otherwise>
   </choose>
    </select>
</mapper> 



when相当于if,otherwise相当于else
也就是说,这里我们有三个条件,id,name,class_id,只能选择一个作为查询条件
如果 id 不为空,那么查询语句为:select * from student where id=?
如果 id 为空,那么看name 是否为空,如果不为空,那么语句为 select * from student where name=?;
如果 name 为空,那么查询语句为 select * from student where class_id=?
trim标签
用于去掉某些内容
- prefix表示语句块,以prefix值为前缀
 - suffix表示语句块,以suffix值为后缀
 - prefixOverrides表示语句块,要去除的前缀
 - suffixOverrides表示语句块,要去除的后缀
 
用 trim 改写上面的 if+where 语句
 <select id="selectStudent" resultType="com.example.demo.Model.Student">
        select * from student
        <trim prefix="where" prefixOverrides="or|and">
            <if test="name!=null">
                name=#{name}
            </if>
            <if test="class_id!=null">
                and class_id=#{class_id}
            </if>
        </trim>
<!--        trim prefix="where" prefixOverrides="or|and" 表示trim标签的语句内,拼接where,去除or、and前缀  -->
    </select>
 

用 trim 改写上面的 set 语句
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.UpdateStudent">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->
<!--    <update id="updateStudent" >-->
<!--   update student-->
<!--        <set>-->
<!--            <if test="id!=null">-->
<!--                id=#{id}-->
<!--            </if>-->
<!--            <if test="name!=null">-->
<!--                 ,name=#{name}-->
<!--            </if>-->
<!--            <trim prefix="" suffix="" prefixOverrides="" suffixOverrides="">-->
<!--            </trim>-->
<!--        </set>-->
<!--    </update>-->
    <update id="updateStudent" >
        update student
        <trim prefix="set" prefixOverrides="," suffixOverrides=",">
            <if test="id!=null">
                id=#{id},
            </if>
            <if test="name!=null">
                name=#{name},
            </if>
        </trim>
    </update>
</mapper> 
for-each标签

这样写的时候,就要多次 id=#{id},可以使用foreach标签实现循环
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.DeleteSomeStudents">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->
<!--    <delete id="delete" >-->
<!--        delete from student where id=#{id} or id=#{id1} or id=#{id2}-->
<!--    </delete>-->
    <delete id="delete">
<!--        id绑定方法-->
        delete  from student
        <where>
            <!--
                collection:指定输入对象中的集合 例如list,map,或者set 对象
                item:每次遍历生成的对象 我们枚举时是id,id1,id2 而item类似于for循环的变量i
                open:开始遍历时的拼接字符串
                close:结束时拼接的字符串
                separator:遍历对象之间需要拼接的字符串
                 delete from student where id=#{id} or id=#{id1} or id=#{id2}
              -->
            <foreach collection="list" item="id" open="(" close=")" separator="or">
                <if test="id!=null">
                id=#{id}
<!--                delete from student where ( id={#id} or id=#{id} or id=#{id} ) 这里的#{id}是循环遍历的值-->
                </if>
            </foreach>
        </where>
    </delete>
</mapper> 

SQL片段
如果某一SQL的使用频率很高,我们可以把他单独定义,提供代码复用率
1、定义SQL
   <sql id="selectStudentByTd_SQL">
        select * from student
        <where>
            <if test="id!=null">
                id=#{id}
            </if>
        </where>
    </sql> 
2、引用SQL
    <select id="selectById" resultType="com.example.demo.Model.Student">
       <!-- 如果refid 指定的不在本文件中,给引用前缀加上namespace,指定SQL片段所在文件 所对应的接口-->
        <include refid="com.example.demo.Mapper.DeleteSomeStudents.selectStudentByTd_SQL"></include>
    </select> 
 




![[C]带你了解C语言是如何操作文件的](https://img-blog.csdnimg.cn/201a2a531024480f8d69fcfab5061b31.png)















