MyBatis SQL映射文件的作用和结构详解

 更新时间:2025年03月10日 09:30:09   作者:冰糖心书房  
MyBatisSQL映射文件定义了SQL语句和参数映射规则,用于将Java代码与数据库操作解耦,实现SQL语句的灵活配置和动态生成

MyBatis SQL 映射文件定义了 SQL 语句以及如何将 SQL 语句的参数和结果映射到 Java 对象。

一、 作用 (Purpose)

MyBatis SQL 映射文件(通常命名为 XXXMapper.xml)的主要作用是:

  1. 定义 SQL 语句: 在 XML 映射文件中编写 SQL 语句,包括 SELECT, INSERT, UPDATE, DELETE 等各种类型的 SQL 语句。
  2. 参数映射 (Parameter Mapping): 定义如何将 Java 方法的参数映射到 SQL 语句中的参数。 可以使用 #$ 占位符,并指定参数类型、jdbcType 等信息。
  3. 结果映射 (Result Mapping): 定义如何将 SQL 语句的查询结果映射到 Java 对象。 可以使用 resultTyperesultMap,并定义一对一、一对多等关系映射。
  4. 动态 SQL (Dynamic SQL): 使用 MyBatis 提供的动态 SQL 元素 (例如 <if>, <choose>, <when>, <otherwise>, <where>, <set>, <foreach>),根据不同的条件动态生成 SQL 语句。
  5. 缓存配置 (Cache Configuration): 配置 SQL 语句的缓存行为,提高查询性能。
  6. 与 Mapper 接口关联: 将 SQL 映射文件与 Java Mapper 接口关联起来,使得可以通过调用 Mapper 接口的方法来执行 SQL 语句。

总而言之,SQL 映射文件是 MyBatis 将 SQL 语句与 Java 代码解耦的关键,它允许开发者专注于 SQL 语句的编写和优化,而无需关心 JDBC 的细节。

二、 结构 (Structure)

MyBatis SQL 映射文件的根元素是 <mapper>,它包含多个子元素,用于定义 SQL 语句、参数映射、结果映射等信息。

以下是一个典型的 SQL 映射文件结构:

<?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.mapper.UserMapper">

    <!-- 1. cache (缓存) -->
    <cache
            eviction="LRU"
            flushInterval="60000"
            readOnly="true"
            size="512"/>

    <!-- 2. resultMap (结果映射) -->
    <resultMap id="UserResultMap" type="com.example.model.User">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="email" column="email"/>
        <!-- association (一对一) -->
        <association property="address" column="address_id" javaType="com.example.model.Address"
                     select="com.example.mapper.AddressMapper.selectAddressById"/>
        <!-- collection (一对多) -->
        <collection property="orders" column="id" ofType="com.example.model.Order"
                    select="com.example.mapper.OrderMapper.selectOrdersByUserId"/>
    </resultMap>

    <!-- 3. select (查询) -->
    <select id="selectUserById" parameterType="int" resultMap="UserResultMap" useCache="true">
        SELECT * FROM user WHERE id = #{id}
    </select>

    <!-- 4. insert (插入) -->
    <insert id="insertUser" parameterType="com.example.model.User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user (username, email) VALUES (#{username}, #{email})
    </insert>

    <!-- 5. update (更新) -->
    <update id="updateUser" parameterType="com.example.model.User">
        UPDATE user SET username = #{username}, email = #{email} WHERE id = #{id}
    </update>

    <!-- 6. delete (删除) -->
    <delete id="deleteUserById" parameterType="int">
        DELETE FROM user WHERE id = #{id}
    </delete>

    <!-- 7. sql (SQL 片段) -->
    <sql id="userColumns">
        id, username, email
    </sql>

</mapper>

三、各个元素详解

<mapper> (根元素):

  • namespace 属性:指定 Mapper 接口的完全限定名。 MyBatis 会根据这个命名空间来查找 SQL 映射文件,并将 SQL 语句与 Mapper 接口的方法关联起来。 这是将 SQL 映射文件与 Java 代码关联的关键。
  • 例如:<mapper namespace="com.example.mapper.UserMapper"> 对应着 UserMapper.java 接口文件

<cache> (缓存):

  • 配置该 Mapper 对应的二级缓存。
  • eviction 属性:指定缓存的淘汰策略 (LRU, FIFO, SOFT, WEAK)。
  • flushInterval 属性:指定缓存的刷新间隔 (毫秒)。
  • size 属性:指定缓存的最大容量。
  • readOnly 属性:指定缓存是否只读 (truefalse)。
  • <cache type="org.mybatis.cache.impl.PerpetualCache"/> 使用自定义缓存

<cache-ref> (缓存引用):

  • 引用其他 Mapper 的缓存配置。
  • namespace 属性:指定要引用的 Mapper 的命名空间。

<resultMap> (结果映射):

作用: 定义如何将 SQL 语句的查询结果映射到 Java 对象。

  • id 属性:指定 resultMap 的唯一标识。
  • type 属性:指定要映射的 Java 类型。

子元素:

  • <id>:定义主键映射。
    • property 属性:指定 Java 对象的属性名。
    • column 属性:指定数据库表中的列名。
  • <result>:定义普通属性映射。
    • property 属性:指定 Java 对象的属性名。
    • column 属性:指定数据库表中的列名。
  • <association>:定义一对一关系映射。
    • property 属性:指定 Java 对象的属性名。
    • column 属性:指定数据库表中的列名。
    • javaType 属性:指定关联对象的 Java 类型。
    • select 属性:指定用于查询关联对象的 SQL 语句的 ID。
  • <collection>:定义一对多关系映射。
    • property 属性:指定 Java 对象的属性名。
    • column 属性:指定数据库表中的列名。
    • ofType 属性:指定集合中元素的 Java 类型。
    • select 属性:指定用于查询集合元素的 SQL 语句的 ID。
  • <discriminator>:定义鉴别器,根据不同的条件选择不同的映射规则。
    • column 属性:指定用于鉴别的列名。
    • <case> 元素:定义不同的映射规则。
      • value 属性:指定鉴别值。
      • resultMap 属性:指定要使用的 resultMap

示例:

<resultMap id="UserResultMap" type="com.example.model.User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <result property="email" column="email"/>
    <association property="address" column="address_id" javaType="com.example.model.Address"
                 select="com.example.mapper.AddressMapper.selectAddressById"/>
    <collection property="orders" column="id" ofType="com.example.model.Order"
                select="com.example.mapper.OrderMapper.selectOrdersByUserId"/>
</resultMap>

<select> (查询):

  • 作用: 定义 SELECT 语句,用于查询数据。
  • id 属性:指定 SQL 语句的唯一标识。 与 Mapper 接口中的方法名对应。
  • parameterType 属性:指定参数类型。
  • resultType 属性:指定结果类型(如果使用简单类型映射)。
  • resultMap 属性:指定结果映射 (如果使用 <resultMap> 元素)。
  • parameterMap 属性: (已经过时, 不建议使用)
  • flushCache 属性: 如果设置为 true,则每次执行该语句都会刷新缓存。
  • useCache 属性:如果设置为 true,则该语句的结果会被缓存。
  • timeout 属性:设置超时时间(秒)。
  • fetchSize 属性:设置每次从数据库获取的记录数量。
  • statementType 属性: 指Statement类型, 可选值为 STATEMENT、PREPARED 和 CALLABLE。
  • STATEMENT, 默认值, 使用Statement
  • PREPARED, 使用PreparedStatement, 可以防止SQL注入, 性能更好。
  • CALLABLE, 主要用于执行存储过程

示例:

<select id="selectUserById" parameterType="int" resultMap="UserResultMap" useCache="true">
    SELECT * FROM user WHERE id = #{id}
</select>

<insert> (插入):

  • 作用: 定义 INSERT 语句,用于插入数据。
  • id 属性:指定 SQL 语句的唯一标识。
  • parameterType 属性:指定参数类型。
  • useGeneratedKeys 属性:是否允许 MyBatis 使用 JDBC 的 getGeneratedKeys 方法获取自增主键值。
  • keyProperty 属性:指定 Java 对象的哪个属性用于接收自增主键值。
  • keyColumn属性:指定数据库表的主键列名.

示例:

<insert id="insertUser" parameterType="com.example.model.User" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
    INSERT INTO user (username, email) VALUES (#{username}, #{email})
</insert>

<update> (更新):

  • 作用: 定义 UPDATE 语句,用于更新数据。
  • id 属性:指定 SQL 语句的唯一标识。
  • parameterType 属性:指定参数类型。

示例:

<update id="updateUser" parameterType="com.example.model.User">
    UPDATE user SET username = #{username}, email = #{email} WHERE id = #{id}
</update>

<delete> (删除):

  • 作用: 定义 DELETE 语句,用于删除数据。
  • id 属性:指定 SQL 语句的唯一标识。
  • parameterType 属性:指定参数类型。

示例:

<delete id="deleteUserById" parameterType="int">
    DELETE FROM user WHERE id = #{id}
</delete>

<sql> (SQL 片段):

  • 作用: 定义可以重复使用的 SQL 代码片段。
  • id 属性:指定 SQL 片段的唯一标识。

示例:

<sql id="userColumns">
    id, username, email
</sql>

四、动态 SQL 元素 (Dynamic SQL Elements)

MyBatis 提供了以下动态 SQL 元素,可以根据不同的条件动态生成 SQL 语句:

<if>

  • 作用: 根据条件判断是否包含某段 SQL 代码。
  • test 属性:指定判断条件,使用 OGNL 表达式。

示例:

<select id="selectUserByCondition" parameterType="com.example.model.User" resultMap="UserResultMap">
    SELECT * FROM user
    <where>
        <if test="username != null and username != ''">
            AND username = #{username}
        </if>
        <if test="email != null and email != ''">
            AND email = #{email}
        </if>
    </where>
</select>

<choose>, <when>, <otherwise>

  • 作用: 类似于 Java 中的 switch-case 语句,用于选择其中一个条件分支。
  • <choose> 元素:包含多个 <when> 元素和一个 <otherwise> 元素。
  • <when> 元素:指定条件和对应的 SQL 代码。
  • <otherwise> 元素:指定默认的 SQL 代码(当所有 <when> 条件都不满足时执行)。
  • test 属性:指定 <when> 元素的判断条件,使用 OGNL 表达式。

示例:

<select id="selectUserByCondition" parameterType="com.example.model.User" resultMap="UserResultMap">
    SELECT * FROM user
    <where>
        <choose>
            <when test="username != null and username != ''">
                AND username = #{username}
            </when>
            <when test="email != null and email != ''">
                AND email = #{email}
            </when>
            <otherwise>
                AND 1 = 1
            </otherwise>
        </choose>
    </where>
</select>

<where>

  • 作用: 动态生成 WHERE 子句,并自动处理 ANDOR 关键字。
  • 如果 <where> 元素内部有任何内容,它会自动添加 WHERE 关键字。
  • 如果 <where> 元素内部的内容以 ANDOR 开头,它会自动移除这些关键字。

示例:

<select id="selectUserByCondition" parameterType="com.example.model.User" resultMap="UserResultMap">
    SELECT * FROM user
    <where>
        <if test="username != null and username != ''">
            AND username = #{username}
        </if>
        <if test="email != null and email != ''">
            AND email = #{email}
        </if>
    </where>
</select>

<set>

  • 作用: 动态生成 SET 子句,用于 UPDATE 语句,并自动处理逗号 ,
  • 如果 <set> 元素内部有任何内容,它会自动添加 SET 关键字。
  • 如果 <set> 元素内部的内容以逗号 , 开头,它会自动移除这个逗号。

示例:

<update id="updateUserSelective" parameterType="com.example.model.User">
    UPDATE user
    <set>
        <if test="username != null">
            username = #{username},
        </if>
        <if test="email != null">
            email = #{email},
        </if>
    </set>
    WHERE id = #{id}
</update>

<trim>

  • 作用: 更通用的动态 SQL 元素,可以自定义前缀、后缀、以及前缀和后缀要移除的内容。
  • prefix 属性:指定前缀。
  • suffix 属性:指定后缀。
  • prefixOverrides 属性:指定要移除的前缀。
  • suffixOverrides 属性:指定要移除的后缀。

示例:

<select id="selectUserByCondition" parameterType="com.example.model.User" resultMap="UserResultMap">
    SELECT * FROM user
    <trim prefix="WHERE" prefixOverrides="AND |OR">
        <if test="username != null and username != ''">
            AND username = #{username}
        </if>
        <if test="email != null and email != ''">
            AND email = #{email}
        </if>
    </trim>
</select>

<update id="updateUserSelective" parameterType="com.example.model.User">
    UPDATE user
    <trim prefix="SET" suffixOverrides=",">
        <if test="username != null">
            username = #{username},
        </if>
        <if test="email != null">
            email = #{email},
        </if>
    </trim>
    WHERE id = #{id}
</update>

<foreach>

  • 作用: 用于遍历集合,生成重复的 SQL 代码。
  • collection 属性:指定要遍历的集合。
  • item 属性:指定集合中元素的别名。
  • index 属性:指定当前元素的索引的别名。
  • open 属性:指定循环开始时的字符串。
  • close 属性:指定循环结束时的字符串。
  • separator 属性:指定元素之间的分隔符。

示例:

<select id="selectUsersByIds" parameterType="list" resultMap="UserResultMap">
    SELECT * FROM user
    WHERE id IN
    <foreach item="id" collection="list" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>

<insert id="insertUsers" parameterType="list">
    INSERT INTO user (username, email) VALUES
    <foreach item="user" collection="list" separator="," >
        (#{user.username}, #{user.email})
    </foreach>
</insert>

<bind>

  • 作用: 创建一个变量,并将其绑定到 OGNL 表达式的结果。
  • name 属性: 指定变量名
  • value 属性: 指定 OGNL 表达式

示例:

<select id="selectUsersBySearchTerm" parameterType="string" resultMap="UserResultMap">
    <bind name="pattern" value="'%' + searchTerm + '%'" />
    SELECT * FROM user
    WHERE username LIKE #{pattern} OR email LIKE #{pattern}
</select>

五、DOCTYPE (Document Type Definition)

MyBatis SQL 映射文件需要遵循特定的 DTD 约束.

DTD 声明:

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

DTD 文件:

  • mybatis-3-mapper.dtd 文件定义了 MyBatis SQL 映射文件的结构。可以在 MyBatis 的官方网站上找到该文件。
  • 开发中通常不需要我们手动修改 DTD 文件,只需要在 XML 配置文件中声明 DTD 即可。

六、总结

MyBatis SQL 映射文件是 MyBatis 框架的核心,它定义了 SQL 语句以及如何将 SQL 语句的参数和结果映射到 Java 对象。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot实现分页功能

    SpringBoot实现分页功能

    这篇文章主要为大家详细介绍了SpringBoot实现分页功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Java HashMap的工作原理

    Java HashMap的工作原理

    这篇文章主要介绍了Java HashMap的工作原理的相关资料,需要的朋友可以参考下
    2016-03-03
  • Spring MVC环境中文件上传功能的实现方法详解

    Spring MVC环境中文件上传功能的实现方法详解

    文件上传是大家应该都不陌生的一个功能,最近在开发中就又遇到了这个需求,所以想着总结一下方便以后需要的时候参考,下面这篇文章主要给大家介绍了关于Spring MVC环境中文件上传功能的实现方法,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-10-10
  • SpringBoot整合Shiro和Redis的示例代码

    SpringBoot整合Shiro和Redis的示例代码

    这篇文章主要介绍了SpringBoot整合Shiro和Redis的示例代码,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • Java中字符串的一些常见方法分享

    Java中字符串的一些常见方法分享

    这篇文章主要介绍了Java中字符串的一些常见方法,需要的朋友可以参考下
    2014-02-02
  • 详解java基础--提示对话框的使用

    详解java基础--提示对话框的使用

    这篇文章主要介绍了java基础--提示对话框的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Java中Quartz高可用定时任务快速入门

    Java中Quartz高可用定时任务快速入门

    如果你想做定时任务,有高可用方面的需求,或者仅仅想入门快,上手简单,那么选用它准没错,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • 老生常谈Java String字符串(必看篇)

    老生常谈Java String字符串(必看篇)

    下面小编就为大家带来一篇老生常谈Java String字符串(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • 解决线程池中ThreadGroup的坑

    解决线程池中ThreadGroup的坑

    这篇文章主要介绍了解决线程池中ThreadGroup的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Spring Boot RestTemplate提交表单数据的三种方法

    Spring Boot RestTemplate提交表单数据的三种方法

    本篇文章主要介绍了Spring Boot RestTemplate提交表单数据的三种方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03

最新评论