0


MyBatis:映射配置文件

本篇内容包括:映射配置 Demo、 select 语句属性详解、resultType&resultMap 注解的使用、 #{} 与 ${} 的区别、动态 SQL 相关标签(if、where、set等)以及MyBatis 映射关联查询(一对多、多对一、多对多)。

一、映射文件基础内容

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

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

1、映射配置 Demo

<?xml version="1.0" encoding="UTF-8" ?><!--MyBatis的DTD约束--><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--
    mapper:核心根标签
    namespace属性:名称空间
--><mappernamespace="StudentMapper"><!--
        select:查询功能的标签
        id属性:唯一标识
        resultType属性:指定结果映射对象类型
        parameterType属性:指定参数映射对象类型
    --><!--    查询功能的标签--><selectid="selectAll"resultType="student">
        SELECT *
        FROM student
    </select><selectid="selectById"resultType="com.bean.student"parameterType="int">
        SELECT *
        FROM student
        WHERE id = #{id}
    </select><!--    插入功能的标签--><insertid="insert"parameterType="student">
        INSERT INTO student
        VALUES (#{id}, #{name}, #{age})
    </insert><!--    修改功能的标签--><updateid="update"parameterType="student">
        UPDATE student
        SET name = #{name},
            age  = #{age}
        WHERE id = #{id}
    </update><!--    删除功能的标签--><deleteid="delete"parameterType="int">
        DELETE
        FROM student
        WHERE id = #{id}
    </delete></mapper>

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 可表示返回基本类型,也可表示返回自定义对象类型

返回基本类型:

<selectid="listUserInfo"resultType="int">
     SELECT userId FROM user_info
</select>

返回自定义类型:

<selectid="getUserInfoById"resultType="UserInfo">
     SELECT user_name ,user_addr FROM user_info WHERE user_id=#{user_id}
</select>

4、关于 resultMap

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

举个栗子:

定义一个 JavaBean:

@Getter@SetterpublicclassUserInfo{String userName;String addr;}

JavaBean 对应的 sql 语句:

DROPTABLEIFEXISTS`user_info`;CREATETABLE`user_info`(`user_id`int(5)NOTNULLAUTO_INCREMENT,`user_name`varchar(50)CHARACTERSET latin1 COLLATE latin1_swedish_ci NOTNULL,`user_addr`varchar(100)CHARACTERSET latin1 COLLATE latin1_swedish_ci NOTNULL,PRIMARYKEY(`user_id`)USINGBTREE)ENGINE=InnoDBAUTO_INCREMENT=16CHARACTERSET= latin1 COLLATE= latin1_swedish_ci ROW_FORMAT = Compact;SET FOREIGN_KEY_CHECKS =1;

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

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

<resultMapid="userInfoMap"type="UserInfo"><resultproperty="userName"column="user_name"/><resultproperty="addr"column="user_addr"/></resultMap>

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> 标签:条件判断

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

<iftest="判断条件"> SQL语句 </if>

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

<selectid="selectUserByUsernameAndSex"resultType="User"parameterType="User">
    select * from user where username=#{username} and sex=#{sex}
</select>

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

<selectid="selectAllWebsite"resultMap="myResult">  
    SELECT id,name,url 
    FROM website 
    WHERE 1=1    
   <iftest="name != null">        
       AND name like #{name}   
   </if><iftest="url!= null">        
       AND url like #{url}    
   </if></select>

2、<where> + <if> 标签

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>

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

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

3、<set> + <if> 标签

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>

4、choose(when,otherwise) 语句

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

<selectid="selectUserByChoose"resultType="com.ys.po.User"parameterType="com.ys.po.User">
      select * from user
      <where><choose><whentest="id !='' and id != null">
                  id=#{id}
              </when><whentest="username !='' and username != null">
                  and username=#{username}
              </when><otherwise>
                  and sex=#{sex}
              </otherwise></choose></where></select>
  • 在上面代码中,我们有三个条件,id,username,sex,只能选择一个作为查询条件- 如果 id 不为空,那么查询语句为:select * from user where id=?;- 如果 id 为空,那么看username 是否为空,如果不为空,那么语句为 select * from user where username=?;- 如果 username 为空,那么查询语句为 select * from user where sex=?;

5、<trim> 格式化的标记

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

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

<selectid="selectUserByUsernameAndSex"resultType="user"parameterType="com.ys.po.User">
        select * from user
        <trimprefix="where"prefixOverrides="and"><iftest="username != null">
               and username=#{username}
            </if><iftest="sex != null">
               and sex=#{sex}
            </if></trim></select>
  • prefix:前缀
  • prefixoverride:去掉第一个 and 或者是 or

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

<!-- 根据 id 更新 user 表的数据 --><updateid="updateUserById"parameterType="com.ys.po.User">
        update user u
            <trimprefix="set"suffixOverrides=","><iftest="username != null and username != ''">
                    u.username = #{username},
                </if><iftest="sex != null and sex != ''">
                    u.sex = #{sex},
                </if></trim>
         
         where id=#{id}
    </update>
  • suffix:后缀
  • suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)

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

<insertid="add">
        insert  into student
        <trimprefix="("suffix=")"suffixOverrides=","><iftest="sname != null">sname,</if><iftest="spwd != null">spwd,</if><iftest="sex != null">sex,</if><iftest="phone != null">phone,</if></trim><trimprefix="values ("suffix=")"suffixOverrides=","><iftest="sname != null">#{sname},</if><iftest="spwd != null">#{spwd},</if><iftest="sex != null">#{sex},</if><iftest="phone != null">#{phone}</if></trim></insert>

6、<foreach> 标签

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

//批量查询
<selectid="findAll"resultType="Student"parameterType="Integer"><includerefid="selectvp"/> WHERE sid in
    <foreachitem="ids"collection="array"open="("separator=","close=")">
        #{ids}
    </foreach></select>
//批量删除
<deleteid="del"parameterType="Integer">
    DELETE FROM student where sid in
    <foreachitem="ids"collection="array"open="("separator=","close=")">
        #{ids}
    </foreach></delete>

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

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

7、<sql>:可重用语句

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

举个栗子:

<sqlid="userColumns"> ${alias}.id,${alias}.username,${alias}.addr </sql>

引定义好的 Sql:

<selectid="listUserInfo"resultMap="userInfoMap">
        SELECT
        <includerefid="userColumns"><propertyname="alias"value="t1"/></include>
        FROM user_info t1
    </select>

三、MyBatis 映射关联查询

1、一对多映射

<!--一对多--><resultMapid="myStudent1"type="student1"><idproperty="sid"column="sid"/><resultproperty="sname"column="sname"/><resultproperty="sex"column="sex"/><resultproperty="sage"column="sage"/><collectionproperty="list"ofType="teacher"><idproperty="tid"column="tid"/><resultproperty="tname"column="tname"/><resultproperty="tage"column="tage"/></collection></resultMap><!--一对多--><selectid="find1"resultMap="myStudent1">
        select *
        from student1 s
                 left join teacher t on s.sid = t.sid
    </select>

2、多对一映射

<!--多对一--><resultMapid="myTeacher"type="teacher"><idproperty="tid"column="tid"/><resultproperty="tname"column="tname"/><resultproperty="tage"column="tage"/><associationproperty="student1"javaType="Student1"><idproperty="sid"column="sid"/><resultproperty="sname"column="sname"/><resultproperty="sex"column="sex"/><resultproperty="sage"column="sage"/></association></resultMap><!--多对一--><selectid="find2"resultMap="myTeacher">
        select *
        from teacher t
                 right join student1 s on t.sid = s.sid
    </select>

3、多对多映射

<!--多对多 以谁为主表查询的时候,主表约等于1的一方,另一方相当于多的一方--><selectid="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>
标签: mybatis java

本文转载自: https://blog.csdn.net/weixin_45187434/article/details/127530718
版权归原作者 栗筝i 所有, 如有侵权,请联系我们删除。

“MyBatis:映射配置文件”的评论:

还没有评论