• MyBatis:映射配置文件


    MyBatis映射配置文件



    一、映射文件基础内容

    MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。

    映射配置文件(mapper文件)中包含了要执行的 SQL 语句以及相应的数据和对象之间的映射关系。

    1. 映射配置

    <?xml version="1.0" encoding="UTF-8" ?>
    <!--MyBatisDTD约束-->
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--
        mapper:核心根标签
        namespace属性:名称空间
    -->
    <mapper namespace="StudentMapper">
        <!--
            select:查询功能的标签
            id属性:唯一标识
            resultType属性:指定结果映射对象类型
            parameterType属性:指定参数映射对象类型
        -->
        <!--    查询功能的标签-->
        <select id="selectAll" resultType="student">
            SELECT *
            FROM student
        </select>
    
        <select id="selectById" resultType="com.bean.student" parameterType="int">
            SELECT *
            FROM student
            WHERE id = #{id}
        </select>
    
        <!--    插入功能的标签-->
        <insert id="insert" parameterType="student">
            INSERT INTO student
            VALUES (#{id}, #{name}, #{age})
        </insert>
    
        <!--    修改功能的标签-->
        <update id="update" parameterType="student">
            UPDATE student
            SET name = #{name},
                age  = #{age}
            WHERE id = #{id}
        </update>
    
        <!--    删除功能的标签-->
        <delete id="delete" parameterType="int">
            DELETE
            FROM student
            WHERE id = #{id}
        </delete>
    </mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    2. 关于 select 语句属性

    select 语句有很多属性:

    • id – 唯一标识 select 语句
    • parameterType --参数类型
    • paramerterMap – 参数映射
    • resultType – 返回类型
    • resultMap – 返回类型映射
    • flushCache – 当语句被调用时,是否清除本地缓存或二级缓存
    • useCache – 是否使用二级缓存
    • timeout – 在抛出异常之前,驱动程序等待数据库返回请求结果的秒数
    • fetchSize – 每次批量返回的结果行数
    • statementType – 使用 STATEMENT,PREPARED 或 CALLABLE 的一个
    • resultSetType – 使用 FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE
      中的一个

    3. 关于 resultType

    resultType 可表示返回基本类型,也可表示返回自定义对象类型

    返回基本类型:

    <select id="listUserInfo" resultType="int">
         SELECT userId FROM user_info
    </select>
    
    • 1
    • 2
    • 3

    返回自定义类型:

    <select id="getUserInfoById" resultType="UserInfo">
         SELECT user_name ,user_addr FROM user_info WHERE user_id=#{user_id}
    </select>
    
    • 1
    • 2
    • 3

    4. 关于 resultMap

    resultMap 主要解决 TABLE 字段与 JavaBean 映射不匹配问题。

    定义一个 JavaBean:

    @Getter
    @Setter
    public class UserInfo {
        String userName;
        String addr;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    JavaBean 对应的 sql 语句:

    DROP TABLE IF EXISTS `user_info`;
    CREATE TABLE `user_info`  (
      `user_id` int(5) NOT NULL AUTO_INCREMENT,
      `user_name` varchar(50) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
      `user_addr` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
      PRIMARY KEY (`user_id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact;
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    JavaBean 与 Sql 语句中,user_name 与 userName 不匹配,user_addr 与 addr 不匹配。

    通过 resultMap 就能很好地解决该问题

    <resultMap id="userInfoMap" type="UserInfo">
       <result property="userName" column="user_name"/>
       <result property="addr" column="user_addr"/>
    resultMap>
    
    • 1
    • 2
    • 3
    • 4

    property 表示 JavaBean 属性,column 表示 table 表字段。

    5. 关于占位符 #{} 与 ${}

    在映射文件的 Sql 语句中 #{} 表示占位符,相当于 ‘?’,${} 需要经过预处理,能防止SQL漏洞注入。

    • #{} 是预编译处理,${} 是字符串替换。
    • #{},采用的是占位符形式,参数化执行,防止SQL注入,底层原理使用 PreparedStatement 对象。
    • ${},采用的是字符串替换,不能防止SQL注入,底层原理使用 Statement 对象。

    二、映射文件动态SQL

    动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

    使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

    动态 SQL 的原理是:使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接 sql,以此来完成动态 sql 的功能。

    MyBatis 中的动态 SQL 标签主要包括:

    元素作用备注
    if判断语句单条件分支判断
    choose(when、otherwise)相当于 Java 中的 switch case 语句多条件分支判断
    trim,where 辅助元素用于处理一些SQL拼装问题
    foreach循环语句在in语句等列举条件常用
    bind辅助元素拼接参数

    1. 标签:条件判断

    if 语句使用方法简单,常常与 test 属性联合使用:

    <if test="判断条件"> SQL语句 if>
    
    • 1

    普通的 Sql 中对于只有一个参数,后面的 #{param} 表示占位符,里面的 param 可以为任意值,对于多个参数则须写清对应的 pojo 类里面的属性

    <select id="selectUserByUsernameAndSex" resultType="User" parameterType="User">
        select * from user where username=#{username} and sex=#{sex}
    select>
    
    • 1
    • 2
    • 3

    在 普通的 Sql 中如果我们想 #{username} 为空情况下就只查 #{sex},这种情况该如何实现呢?使用 if 来判断,可多个 if 语句同时使用。以下语句表示为可以按照网站名称(name)或者网址(url)进行模糊查询。如果您不输入名称或网址,则返回所有的网站记录。但是,如果你传递了任意一个参数,它就会返回与给定参数相匹配的记录。

    <select id="selectAllWebsite" resultMap="myResult">  
        SELECT id,name,url 
        FROM website 
        WHERE 1=1    
       <if test="name != null">        
           AND name like #{name}   
       if>    
       <if test="url!= null">        
           AND url like #{url}    
       if>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2. + 标签

    where、if 同时使用可以进行查询、模糊查询

            SELECT
                *
            FROM
                collection_cost_detail
            <where>
                <if test="collectionBillMainId != null and collectionBillMainId != ''">
                  AND collection_bill_main_id = #{collectionBillMainId}
                if>
                <if test="collectionSubBillType != null and collectionSubBillType != ''">
                  AND collection_sub_bill_type = #{collectionSubBillType}
                if>
                <if test="costType != null and costType != ''">
                  AND cost_type = #{costType}
                if>
            where>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    失败后, 关键字只会去掉库表字段赋值前面的 and,不会去掉语句后面的 and 关键字,即 只会去掉 语句中的最开始的 and 关键字。

    这个 标签会知道如果它包含的标签中有返回值的话,它就插入一个 where。此外,如果标签返回的内容是以 AND 或 OR 开头的,则它会剔除掉。

    3. + 标签

    Set、if 同时使用可以用来修改

    <update id="upd">
            update student
            <set>
                <if test="sname != null">sname=#{sname},if>
                <if test="spwd != null">spwd=#{spwd},if>
                <if test="sex != null">sex=#{sex},if>
                <if test="phone != null">phone=#{phone}if>
            sid=#{sid}
            set>
            where sid=#{sid}
    update>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4. choose(when,otherwise) 语句

    有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句

    <select id="selectUserByChoose" resultType="com.ys.po.User" parameterType="com.ys.po.User">
          select * from user
          <where>
              <choose>
                  <when test="id !='' and id != null">
                      id=#{id}
                  when>
                  <when test="username !='' and username != null">
                      and username=#{username}
                  when>
                  <otherwise>
                      and sex=#{sex}
                  otherwise>
              choose>
          where>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在上面代码中,我们有三个条件,id,username,sex,只能选择一个作为查询条件

    • 如果 id 不为空,那么查询语句为:select * from user where id=?;
    • 如果 id 为空,那么看username 是否为空,如果不为空,那么语句为 select * from user where username=?;
    • 如果 username 为空,那么查询语句为 select * from user where sex=?;

    5. 格式化的标记

    trim 标记是一个格式化的标记,可以完成 set 或者是 where 标记的功能

    用 trim 改写上面第二点的 if+where 语句:

    <select id="selectUserByUsernameAndSex" resultType="user" parameterType="com.ys.po.User">
            select * from user
            <trim prefix="where" prefixOverrides="and">
                <if test="username != null">
                   and username=#{username}
                if>
                <if test="sex != null">
                   and sex=#{sex}
                if>
            trim>
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • prefix:前缀
    • prefixoverride:去掉第一个 and 或者是 or

    用 trim 改写上面第三点的 if+set 语句:

    
        <update id="updateUserById" parameterType="com.ys.po.User">
            update user u
                <trim prefix="set" suffixOverrides=",">
                    <if test="username != null and username != ''">
                        u.username = #{username},
                    if>
                    <if test="sex != null and sex != ''">
                        u.sex = #{sex},
                    if>
                trim>
             
             where id=#{id}
        update>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • suffix:后缀
    • suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)

    trim+if 同时使用可以添加:

    <insert id="add">
            insert  into student
            <trim prefix="(" suffix=")" suffixOverrides=",">
                <if test="sname != null">sname,if>
                <if test="spwd != null">spwd,if>
                <if test="sex != null">sex,if>
                <if test="phone != null">phone,if>
            trim>
            <trim prefix="values (" suffix=")"  suffixOverrides=",">
                <if test="sname != null">#{sname},if>
                <if test="spwd != null">#{spwd},if>
                <if test="sex != null">#{sex},if>
                <if test="phone != null">#{phone}if>
            trim>
    insert>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6. 标签

    foreach是用来对集合的遍历,这个和 Java 中的功能很类似。通常处理 Sql 中的 in 语句。

    //批量查询
    <select id="findAll" resultType="Student" parameterType="Integer">
        <include refid="selectvp"/> WHERE sid in
        <foreach item="ids" collection="array"  open="(" separator="," close=")">
            #{ids}
        </foreach>
    </select>
    //批量删除
    <delete id="del"  parameterType="Integer">
        DELETE FROM student where sid in
        <foreach item="ids" collection="array"  open="(" separator="," close=")">
            #{ids}
        </foreach>
    </delete>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符

    你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

    7. 可重用语句

    在实际开发中会遇到许多相同的SQL,比如根据某个条件筛选,这个筛选很多地方都能用到,我们可以将其抽取出来成为一个公用的部分,这样修改也方便,一旦出现了错误,只需要改这一处便能处处生效了,此时就用到了 这个标签了。 用于引用 标签定义的常量

     <sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.addr sql>
    
    • 1

    引入定义好的 Sql:

        <select id="listUserInfo" resultMap="userInfoMap">
            SELECT
            <include refid="userColumns">
                <property name="alias" value="t1"/>
            include>
            FROM user_info t1
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    三、MyBatis 映射关联查询

    1. 一对多映射

        
        <resultMap id="myStudent1" type="student1">
            <id property="sid" column="sid"/>
            <result property="sname" column="sname"/>
            <result property="sex" column="sex"/>
            <result property="sage" column="sage"/>
            <collection property="list" ofType="teacher">
                <id property="tid" column="tid"/>
                <result property="tname" column="tname"/>
                <result property="tage" column="tage"/>
            collection>
        resultMap>
        
        <select id="find1" resultMap="myStudent1">
            select *
            from student1 s
                     left join teacher t on s.sid = t.sid
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2. 多对一映射

        
        <resultMap id="myTeacher" type="teacher">
            <id property="tid" column="tid"/>
            <result property="tname" column="tname"/>
            <result property="tage" column="tage"/>
            <association property="student1" javaType="Student1">
                <id property="sid" column="sid"/>
                <result property="sname" column="sname"/>
                <result property="sex" column="sex"/>
                <result property="sage" column="sage"/>
            association>
        resultMap>
    
    		
        <select id="find2" resultMap="myTeacher">
            select *
            from teacher t
                     right join student1 s on t.sid = s.sid
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3. 多对多映射

    	
        <select id="find3" resultMap="myStudent1">
            select *
            from student1 s
                     left join relevance r on s.sid = r.sid
                     left join teacher t on r.tid = t.tid
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

  • 相关阅读:
    分布式协同AI基准测试项目Ianvs:工业场景提升5倍研发效率
    【python】程序常见异常&异常处理方法
    基于微信小程序的线上教育课程付费商城(源码+lw+部署文档+讲解等)
    CSShas伪类选择器案例附注释
    Webpack & 基础入门以及接入 CSS、Typescript、Babel
    MyBioSource p53 肿瘤抑制蛋白 (TP53),多克隆抗体
    基于Matlab求解高教社杯全国大学生数学建模竞赛(CUMCM2020A题)-炉温曲线的机理建模与优化(源码+数据)
    泛海微FH511单片机IC方案小家电LED照明MCU丝印FH511
    指令和过滤器的区别及用法
    Apache Hive之数据查询
  • 原文地址:https://blog.csdn.net/weixin_47410172/article/details/127868700