实用指南:MyBatis XML 配置详解

MyBatis XML 配置详解

本文档详细介绍了 MyBatis 框架中 XML 配置方式的使用方法,包括核心配置文件结构、映射文件编写、动态 SQL 以及高级功能配置。

1. MyBatis XML 配置概述

MyBatis 的 XML 配置方式是通过编写 XML 文件来定义 SQL 语句和映射关系,与注解方式相比,XML 方式更适合复杂的 SQL 场景,提供了更好的可读性和维护性。

XML 配置与注解配置对比

  • XML 优势:适合复杂 SQL、动态 SQL、结果映射配置,SQL 与 Java 代码分离
  • 注解优势:简单直观,适合简单的 CRUD 操作

2. 核心配置文件(mybatis-config.xml)

2.1 基本结构

MyBatis 的核心配置文件通常命名为 mybatis-config.xml,遵循固定的元素顺序(顺序必须固定):

<?xml version="1.0" encoding="UTF-8" ?>
  <!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
  <configuration>
  <properties></properties>
  <settings></settings>
  <typeAliases></typeAliases>
  <typeHandlers></typeHandlers>
  <objectFactory></objectFactory>
  <plugins></plugins>
  <environments></environments>
  <databaseIdProvider></databaseIdProvider>
  <mappers></mappers>
  </configuration>

完整配置示例:

<?xml version="1.0" encoding="UTF-8" ?>
  <!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
  <configuration>
    <!--
    1. properties:引入外部属性文件,用于配置数据库连接参数等。
    - resource:从类路径加载属性文件
    - 也可以使用<property>子元素内联定义属性
      -->
        <properties resource="jdbc.properties">
        <property name="jdbc.username" value="root"/>
        <property name="jdbc.password" value="123456"/>
        <!-- 启用占位符默认值特性,允许${key:default}语法 -->
          <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
        </properties>
        <!--
        2. settings:MyBatis的全局核心设置,会改变运行时行为
        -->
        <settings>
          <!-- 启用二级缓存(默认true) -->
            <setting name="cacheEnabled" value="true"/>
            <!-- 启用延迟加载(默认false) -->
              <setting name="lazyLoadingEnabled" value="true"/>
              <!-- 积极的延迟加载开关(3.4.1后默认false) -->
                <setting name="aggressiveLazyLoading" value="false"/>
                <!-- 允许单语句返回多结果集(需要数据库驱动支持) -->
                  <setting name="multipleResultSetsEnabled" value="true"/>
                  <!-- 使用列标签代替列名 -->
                    <setting name="useColumnLabel" value="true"/>
                    <!-- 允许JDBC支持自动生成主键 -->
                      <setting name="useGeneratedKeys" value="false"/>
                      <!-- 自动映射行为:NONE|PARTIAL|FULL -->
                        <setting name="autoMappingBehavior" value="PARTIAL"/>
                        <!-- 自动映射未知列行为:NONE|WARNING|FAILING -->
                          <setting name="autoMappingUnknownColumnBehavior" value="NONE"/>
                          <!-- 默认执行器类型:SIMPLE|REUSE|BATCH -->
                            <setting name="defaultExecutorType" value="SIMPLE"/>
                            <!-- 数据库响应超时时间(秒) -->
                              <setting name="defaultStatementTimeout" value="25"/>
                              <!-- 驱动的结果集获取数量建议值 -->
                                <setting name="defaultFetchSize" value="100"/>
                                <!-- 是否允许在嵌套语句中使用分页(RowBounds) -->
                                  <setting name="safeRowBoundsEnabled" value="false"/>
                                  <!-- 开启驼峰命名自动映射(下划线转驼峰) -->
                                    <setting name="mapUnderscoreToCamelCase" value="true"/>
                                    <!-- 本地缓存作用域:SESSION|STATEMENT -->
                                      <setting name="localCacheScope" value="SESSION"/>
                                      <!-- 空值的默认JDBC类型 -->
                                        <setting name="jdbcTypeForNull" value="OTHER"/>
                                        <!-- 延迟加载的触发方法 -->
                                          <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
                                          <!-- 日志实现 -->
                                            <setting name="logImpl" value="STDOUT_LOGGING"/>
                                            <!-- 当结果集为空时是否返回空实例而非null -->
                                              <setting name="returnInstanceForEmptyRow" value="false"/>
                                            </settings>
                                            <!--
                                            3. typeAliases:为Java类型设置别名,简化XML配置中的类型书写
                                            -->
                                            <typeAliases>
                                              <!-- 为单个类定义别名 -->
                                                <typeAlias type="com.example.entity.User" alias="User"/>
                                                <!-- 扫描整个包,默认别名为类名(首字母小写) -->
                                                  <package name="com.example.entity"/>
                                                </typeAliases>
                                                <!--
                                                4. typeHandlers:注册自定义类型处理器,用于Java类型与JDBC类型转换
                                                -->
                                                <typeHandlers>
                                                  <!-- 注册单个类型处理器 -->
                                                    <typeHandler handler="com.example.handler.DateTypeHandler"/>
                                                    <!-- 扫描包下的所有类型处理器 -->
                                                      <package name="com.example.handler"/>
                                                    </typeHandlers>
                                                    <!--
                                                    5. objectFactory:自定义对象工厂,用于创建结果集对象的实例
                                                    -->
                                                      <objectFactory type="com.example.factory.CustomObjectFactory">
                                                      <property name="someProperty" value="100"/>
                                                    </objectFactory>
                                                    <!--
                                                    6. plugins:注册拦截器,可在SQL执行前后加入自定义逻辑
                                                    -->
                                                    <plugins>
                                                        <plugin interceptor="com.example.plugin.PageInterceptor">
                                                        <property name="dialect" value="mysql"/>
                                                      </plugin>
                                                      <plugin interceptor="com.example.plugin.SqlLogInterceptor"/>
                                                    </plugins>
                                                    <!--
                                                    7. environments:数据库环境配置,支持多环境(如开发、测试、生产)
                                                    default:指定默认使用的环境ID
                                                    -->
                                                      <environments default="development">
                                                      <!-- 开发环境 -->
                                                          <environment id="development">
                                                          <!-- 事务管理器类型:JDBC|MANAGED -->
                                                            <transactionManager type="JDBC"/>
                                                            <!--
                                                            数据源类型:UNPOOLED|POOLED|JNDI
                                                            POOLED:使用连接池
                                                            -->
                                                              <dataSource type="POOLED">
                                                              <property name="driver" value="${jdbc.driver}"/>
                                                              <property name="url" value="${jdbc.url}"/>
                                                              <!-- 使用默认值语法,如果属性不存在则使用默认值 -->
                                                                <property name="username" value="${jdbc.username:root}"/>
                                                                <property name="password" value="${jdbc.password:123456}"/>
                                                                <!-- 连接池特定属性 -->
                                                                  <property name="poolMaximumActiveConnections" value="20"/>
                                                                  <property name="poolMaximumIdleConnections" value="10"/>
                                                                  <property name="poolMaximumCheckoutTime" value="20000"/>
                                                                </dataSource>
                                                              </environment>
                                                              <!-- 生产环境示例 -->
                                                                  <environment id="production">
                                                                  <transactionManager type="JDBC"/>
                                                                    <dataSource type="POOLED">
                                                                    <property name="driver" value="${prod.jdbc.driver}"/>
                                                                    <property name="url" value="${prod.jdbc.url}"/>
                                                                    <property name="username" value="${prod.jdbc.username}"/>
                                                                    <property name="password" value="${prod.jdbc.password}"/>
                                                                  </dataSource>
                                                                </environment>
                                                              </environments>
                                                              <!--
                                                              8. databaseIdProvider:数据库厂商标识,用于根据数据库类型执行不同SQL
                                                              -->
                                                                <databaseIdProvider type="DB_VENDOR">
                                                                <property name="MySQL" value="mysql"/>
                                                                <property name="Oracle" value="oracle"/>
                                                                <property name="PostgreSQL" value="postgresql"/>
                                                              </databaseIdProvider>
                                                              <!--
                                                              9. mappers:注册映射文件或接口,告诉MyBatis到哪里去找SQL映射
                                                              -->
                                                              <mappers>
                                                                <!-- 通过资源路径引用XML映射文件 -->
                                                                  <mapper resource="com/example/mapper/UserMapper.xml"/>
                                                                  <!-- 通过类名引用注解配置的Mapper接口 -->
                                                                    <mapper class="com.example.mapper.UserMapper"/>
                                                                    <!-- 通过包名扫描包下的所有Mapper接口 -->
                                                                      <package name="com.example.mapper"/>
                                                                      <!-- 通过URL引用文件系统上的映射文件 -->
                                                                        <mapper url="file:///var/mappers/UserMapper.xml"/>
                                                                      </mappers>
                                                                    </configuration>

2.2 properties 属性配置

properties 元素用于外部化配置,可以从属性文件或直接内嵌属性值:

<properties resource="jdbc.properties"/>
<properties>
  <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
  <property name="jdbc.url" value="jdbc:"/>
  <property name="jdbc.username" value="root"/>
  <property name="jdbc.password" value="password"/>
</properties>
  <properties resource="jdbc.properties">
  <property name="jdbc.username" value="override_username"/>
</properties>

属性加载优先级:方法参数 > resource/url 读取 > properties 子元素定义

2.3 settings 全局设置

settings 是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为:

<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="mapUnderscoreToCamelCase" value="true"/>
  <setting name="logImpl" value="STDOUT_LOGGING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
</settings>

2.4 typeAliases 类型别名

类型别名可为 Java 类型设置简短名称,减少冗余的全限定类名书写:

<typeAliases>
  <typeAlias alias="User" type="com.example.model.User"/>
  <typeAlias alias="Order" type="com.example.model.Order"/>
</typeAliases>
<typeAliases>
  <package name="com.example.model"/>
</typeAliases>

MyBatis 为常用 Java 类型内建了类型别名,如 string 对应 Stringint 对应 Integermap 对应 Map 等。

2.5 environments 环境配置

environments 用于配置多环境数据源和事务管理器:

<environments default="development">
    <environment id="development">
    <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
      <property name="driver" value="${jdbc.driver}"/>
      <property name="url" value="${jdbc.url}"/>
      <property name="username" value="${jdbc.username}"/>
      <property name="password" value="${jdbc.password}"/>
    </dataSource>
  </environment>
    <environment id="production">
    <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
    </dataSource>
  </environment>
</environments>

2.6 mappers 映射器配置

mappers 用于注册包含 SQL 映射的 Mapper 文件或接口:

<mappers>
  <mapper resource="com/example/mapper/UserMapper.xml"/>
    <mapper class="com.example.mapper.UserMapper"/>
      <package name="com.example.mapper"/>
        <mapper url=""/>
          </mappers>

3. Mapper XML 映射文件

3.1 基本结构

Mapper XML 文件用于定义 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">
    <select></select>
      <insert></insert>
        <update></update>
          <delete></delete>
            <!-- ... -->
              </mapper>

XML 文件开头的文档类型声明 DTD(Document Type Declaration,简称 DOCTYPE)用于定义 XML 文档的结构和约束规则。

组成部分说明
<!DOCTYPE mapper声明此 XML 文档的根元素是 <mapper>
PUBLIC表示这是一个"公开的" DTD,有正式的名称标识
"-//mybatis.org//DTD Mapper 3.0//EN"正式公共标识符(Formal Public Identifier)
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"DTD 文件的实际网络位置

其中:
-//mybatis.org//DTD Mapper 3.0//EN
语言:英语(EN)
文档描述:MyBatis Mapper DTD 版本 3.0
所有者:mybatis.org
注册状态(固定前缀):- 表示未注册,+ 表示已注册

3.2 CRUD 操作标签

<mapper> 标签是 MyBatis 映射文件的根元素,包含以下核心属性:

属性必需描述示例
namespace命名空间,用于隔离不同的 SQL 映射,通常对应 Mapper 接口的全限定名namespace="com.example.mapper.UserMapper"

公共属性(所有CRUD标签共用)

属性适用标签描述默认值可选值
id所有语句唯一标识--
parameterType所有参数类型自动推断类全名/别名
flushCache所有是否清空缓存falsetrue/false
timeout所有超时时间(秒)未设置正整数
statementType所有Statement类型PREPAREDSTATEMENT/PREPARED/CALLABLE
databaseId所有数据库厂商标识-mysql/oracle

Select 特有属性

属性描述默认值
resultType结果类型-
resultMap结果映射引用-
useCache是否使用二级缓存true
fetchSize每次获取记录数驱动决定
resultSetType结果集类型驱动决定

Insert/Update 特有属性

属性描述默认值
useGeneratedKeys使用自增主键false
keyProperty主键属性-
keyColumn主键列名-
3.3.1 select 查询语句
<select id="selectUserById" parameterType="int" resultType="User">
  SELECT id, username, email FROM users WHERE id = #{id}
  </select>
    <select id="selectUsersByCondition" parameterType="map" resultType="User">
      SELECT * FROM users
      WHERE username LIKE CONCAT('%', #{name}, '%')
      AND age > #{minAge}
      ORDER BY ${orderBy} DESC
      LIMIT #{offset}, #{limit}
      </select>
3.3.2 insert 插入语句
<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
  INSERT INTO users (username, email, age)
  VALUES (#{username}, #{email}, #{age})
  </insert>
    <insert id="batchInsertUsers" parameterType="list">
      INSERT INTO users (username, email) VALUES
      <foreach collection="list" item="user" separator=",">
        (#{user.username}, #{user.email})
        </foreach>
          </insert>
3.3.3 update 更新语句
<update id="updateUser" parameterType="User">
  UPDATE users
  SET username = #{username}, email = #{email}, age = #{age}
  WHERE id = #{id}
</update>
3.3.4 delete 删除语句
<delete id="deleteUserById" parameterType="int">
  DELETE FROM users WHERE id = #{id}
</delete>

3.4 参数传递

单个参数

<select id="selectUserById" parameterType="int" resultType="User">
  SELECT * FROM users WHERE id = #{id}
</select>

多个参数(使用 @Param 注解或默认名称):

<select id="selectByNameAndAge" resultType="User">
  SELECT * FROM users WHERE username = #{param1} AND age = #{param2}
</select>

Map 参数

<select id="selectByMap" parameterType="map" resultType="User">
  SELECT * FROM users
  WHERE username = #{name} AND age BETWEEN #{minAge} AND #{maxAge}
</select>

4. 结果映射(ResultMap)

4.1映射表格汇总

ResultMap基本属性表

属性必需描述默认值示例
id结果映射的唯一标识符,在命名空间内必须唯一-id="userMap"
type映射的目标 Java 类型(全限定类名或别名)-type="com.example.User"
extends继承另一个已定义的 resultMap-extends="baseMap"
autoMapping是否开启未明确映射字段的自动映射falseautoMapping="true"

所有子标签功能总结

子标签用途关键属性适用场景
<id>主键映射property, column数据库主键字段
<result>普通字段映射property, column非主键字段
<association>一对一关联property, javaType, select用户-个人资料
<collection>一对多关联property, ofType, select用户-订单列表
<constructor>构造器注入<idArg>, <arg>不可变对象
<discriminator>动态映射选择column, <case>继承关系处理

配置选择指南

场景推荐配置理由
简单字段映射<result> + autoMapping="true"减少配置量
复杂关联查询嵌套结果映射性能更好,单次查询
大数据量关联嵌套查询 + fetchType="lazy"避免内存溢出
继承关系处理<discriminator>结构清晰
不可变对象<constructor>符合设计原则

1) id主键映射标签

用于映射数据库主键字段,MyBatis 使用此标识进行结果集分组和缓存优化。

属性表:

属性必需描述示例
propertyJava 对象属性名property="id"
column数据库列名column="user_id"
javaTypeJava 类型(通常可自动推断)javaType="java.lang.Long"
jdbcTypeJDBC 类型jdbcType="BIGINT"
typeHandler自定义类型处理器typeHandler="com.example.MyTypeHandler"

2) result 普通字段映射标签

用于映射非主键字段。

属性表:

属性必需描述示例
propertyJava 对象属性名property="userName"
column数据库列名column="user_name"
javaTypeJava 类型javaType="java.lang.String"
jdbcTypeJDBC 类型jdbcType="VARCHAR"
typeHandler自定义类型处理器typeHandler="StringTypeHandler"

关联关系映射标签:
3) association一对一关联映射

用于处理"有一个"的关系,如用户有一个个人资料。

属性表:

属性必需描述示例
propertyJava 对象中的关联属性名property="profile"
javaType关联对象的 Java 类型javaType="UserProfile"
resultMap引用已定义的 resultMapresultMap="profileMap"
column传递给嵌套查询的列column="user_id"
select嵌套查询的语句 IDselect="selectProfileById"
fetchType加载策略:lazy/eagerfetchType="lazy"

4) collection一对多关联映射

用于处理"有多个"的关系,如用户有多个订单。

属性表:

属性必需描述示例
propertyJava 对象中的集合属性名property="orders"
ofType集合中元素的 Java 类型ofType="Order"
resultMap引用已定义的 resultMapresultMap="orderMap"
column传递给嵌套查询的列column="id"
select嵌套查询的语句 IDselect="selectOrdersByUserId"
fetchType加载策略:lazy/eagerfetchType="lazy"

4.2 基本结果映射

当数据库列名与 Java 属性名不一致时,使用 resultMap 进行映射:

<!-- 结果集映射 -->
    <resultMap id="userResultMap" type="User">
    <!-- 主键映射 -->
      <id property="id" column="user_id"/>
      <!-- 普通字段映射 -->
        <result property="username" column="user_name"/>
        <result property="email" column="user_email"/>
        <result property="createTime" column="create_time"/>
      </resultMap>
        <select id="selectUserWithMapping" resultMap="userResultMap">
        SELECT user_id, user_name, user_email, create_time FROM users
      </select>
      <!-- 鉴别器 -->
          <discriminator javaType="int" column="type">
          <case value="1" resultMap="adminMap"/>
          <case value="2" resultMap="userMap"/>
        </discriminator>

4.3 关联查询(一对一)

使用 association 处理一对一关联关系:

<resultMap id="userWithProfileMap" type="User">
  <id property="id" column="id"/>
  <result property="username" column="username"/>
  <result property="email" column="email"/>
  <!-- 一对一关联 -->
      <association property="profile" javaType="UserProfile">
      <id property="profileId" column="profile_id"/>
      <result property="realName" column="real_name"/>
      <result property="address" column="address"/>
    </association>
  </resultMap>
    <select id="selectUserWithProfile" resultMap="userWithProfileMap">
    SELECT u.*, p.profile_id, p.real_name, p.address
    FROM users u
    LEFT JOIN user_profiles p ON u.id = p.user_id
    WHERE u.id = #{id}
  </select>

4.4 集合查询(一对多)

使用 collection 处理一对多关联关系:

<resultMap id="userWithOrdersMap" type="User">
  <id property="id" column="id"/>
  <result property="username" column="username"/>
  <result property="email" column="email"/>
  <!-- 一对多关联 -->
      <collection property="orders" ofType="Order">
      <id property="orderId" column="order_id"/>
      <result property="orderNo" column="order_no"/>
      <result property="amount" column="amount"/>
      <result property="createTime" column="order_create_time"/>
    </collection>
  </resultMap>
    <select id="selectUserWithOrders" resultMap="userWithOrdersMap">
    SELECT u.*, o.order_id, o.order_no, o.amount, o.create_time as order_create_time
    FROM users u
    LEFT JOIN orders o ON u.id = o.user_id
    WHERE u.id = #{id}
  </select>

5. 动态 SQL

5.1 if 条件判断

<select id="findUsersByCondition" parameterType="map" resultType="User">
  SELECT * FROM users
  <where>
      <if test="username != null and username != ''">
      AND username LIKE CONCAT('%', #{username}, '%')
    </if>
      <if test="email != null">
      AND email = #{email}
    </if>
      <if test="minAge != null">
      AND age >= #{minAge}
    </if>
      <if test="maxAge != null">
      AND age <= #{maxAge}
    </if>
  </where>
</select>

5.2 choose, when, otherwise 多条件选择

<select id="findUsersDynamic" parameterType="map" resultType="User">
  SELECT * FROM users
  <where>
    <choose>
        <when test="username != null">
        AND username = #{username}
      </when>
        <when test="email != null">
        AND email = #{email}
      </when>
      <otherwise>
        AND status = 'ACTIVE'
      </otherwise>
    </choose>
  </where>
</select>

5.3 foreach 循环遍历

<select id="findUsersByIds" parameterType="list" resultType="User">
  SELECT * FROM users
  WHERE id IN
    <foreach collection="list" item="id" open="(" separator="," close=")">
    #{id}
  </foreach>
</select>
  <insert id="batchInsert" parameterType="list">
  INSERT INTO users (username, email) VALUES
    <foreach collection="list" item="user" separator=",">
    (#{user.username}, #{user.email})
  </foreach>
</insert>

5.4 trim, set 语句优化

<update id="updateUserDynamic" parameterType="User">
  UPDATE users
  <set>
  <if test="username != null">username = #{username},</if>
  <if test="email != null">email = #{email},</if>
  <if test="age != null">age = #{age},</if>
  </set>
  WHERE id = #{id}
</update>

6. 高级功能配置

6.1 <selectKey> 主键处理

<insert id="insertUser" parameterType="User">
    <selectKey keyProperty="id" resultType="Long" order="BEFORE">
    SELECT user_seq.nextval FROM dual
  </selectKey>
  INSERT INTO users (id, name, email) VALUES (#{id}, #{name}, #{email})
</insert>
  <insert id="insertUserMySQL" parameterType="User">
  INSERT INTO users (name, email) VALUES (#{name}, #{email})
    <selectKey keyProperty="id" resultType="Long" order="AFTER">
    SELECT LAST_INSERT_ID()
  </selectKey>
</insert>

6.2 缓存配置

一级缓存:默认开启,SqlSession 级别。

二级缓存配置

<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>
  <select id="selectUserById" parameterType="int" resultType="User" useCache="true">
  SELECT * FROM users WHERE id = #{id}
</select>

6.3 SQL 片段重用

使用 sqlinclude 标签实现 SQL 片段重用:

<sql id="userColumns">
  id, username, email, age, create_time
</sql>
  <sql id="userTable">
  users
</sql>
  <select id="selectAllUsers" resultType="User">
  SELECT
  <include refid="userColumns"/>
  FROM
  <include refid="userTable"/>
</select>
  <sql id="dynamicWhere">
  <where>
  <if test="username != null">AND username = #{username}</if>
  <if test="status != null">AND status = #{status}</if>
  </where>
</sql>
  <select id="findUsers" parameterType="map" resultType="User">
  SELECT <include refid="userColumns"/>
  FROM <include refid="userTable"/>
  <include refid="dynamicWhere"/>
</select>

7. 类型处理器(TypeHandlers)

自定义类型处理器处理特殊数据类型转换:

<typeHandlers>
    <typeHandler handler="com.example.handler.JsonTypeHandler"
    javaType="com.example.model.JsonData"/>
</typeHandlers>
// 自定义类型处理器实现
public class JsonTypeHandler extends BaseTypeHandler<JsonData> {
  @Override
  public void setNonNullParameter(PreparedStatement ps, int i,
  JsonData parameter, JdbcType jdbcType) throws SQLException {
  ps.setString(i, parameter.toJson());
  }
  @Override
  public JsonData getNullableResult(ResultSet rs, String columnName) throws SQLException {
  return JsonData.fromJson(rs.getString(columnName));
  }
  }

8. 插件(Plugins)配置

配置 MyBatis 插件实现拦截器功能:

<plugins>
    <plugin interceptor="com.example.plugin.SqlLogPlugin">
    <property name="enableLog" value="true"/>
  </plugin>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
    <property name="helperDialect" value="mysql"/>
    <property name="reasonable" value="true"/>
  </plugin>
</plugins>

9. 完整配置示例

9.1 完整的 mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
  <!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
  <configuration>
      <properties resource="jdbc.properties">
      <property name="logEnabled" value="true"/>
    </properties>
    <settings>
      <setting name="cacheEnabled" value="true"/>
      <setting name="lazyLoadingEnabled" value="true"/>
      <setting name="mapUnderscoreToCamelCase" value="true"/>
      <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <typeAliases>
      <package name="com.example.model"/>
    </typeAliases>
    <plugins>
      <plugin interceptor="com.example.plugin.SqlLogPlugin"/>
    </plugins>
      <environments default="development">
        <environment id="development">
        <transactionManager type="JDBC"/>
          <dataSource type="POOLED">
          <property name="driver" value="${jdbc.driver}"/>
          <property name="url" value="${jdbc.url}"/>
          <property name="username" value="${jdbc.username}"/>
          <property name="password" value="${jdbc.password}"/>
        </dataSource>
      </environment>
    </environments>
    <mappers>
      <package name="com.example.mapper"/>
    </mappers>
  </configuration>

9.2 完整的 Mapper XML 示例

<?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">
    <resultMap id="userDetailMap" type="User">
      <id property="id" column="id"/>
        <result property="username" column="username"/>
          <result property="email" column="email"/>
            <result property="age" column="age"/>
              <result property="createTime" column="create_time"/>
                <!-- 一对一关联 -->
                  <association property="profile" javaType="UserProfile">
                    <id property="id" column="profile_id"/>
                      <result property="realName" column="real_name"/>
                        </association>
                          <!-- 一对多关联 -->
                            <collection property="orders" ofType="Order">
                              <id property="id" column="order_id"/>
                                <result property="orderNo" column="order_no"/>
                                  <result property="amount" column="amount"/>
                                    </collection>
                                      </resultMap>
                                        <sql id="userColumns">
                                          u.id, u.username, u.email, u.age, u.create_time
                                          </sql>
                                            <select id="findUsersByCondition" parameterType="map" resultMap="userDetailMap">
                                              SELECT
                                              <include refid="userColumns"/>,
                                                p.id as profile_id, p.real_name,
                                                o.id as order_id, o.order_no, o.amount
                                                FROM users u
                                                LEFT JOIN user_profiles p ON u.id = p.user_id
                                                LEFT JOIN orders o ON u.id = o.user_id
                                                <where>
                                                  <if test="username != null and username != ''">
                                                    AND u.username LIKE CONCAT('%', #{username}, '%')
                                                    </if>
                                                      <if test="minAge != null">
                                                        AND u.age >= #{minAge}
                                                        </if>
                                                          <if test="maxAge != null">
                                                            AND u.age <= #{maxAge}
                                                            </if>
                                                              <if test="statusList != null and statusList.size() > 0">
                                                                AND u.status IN
                                                                <foreach collection="statusList" item="status" open="(" separator="," close=")">
                                                                  #{status}
                                                                  </foreach>
                                                                    </if>
                                                                      </where>
                                                                        ORDER BY u.create_time DESC
                                                                        </select>
                                                                          <insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
                                                                            INSERT INTO users (username, email, age, create_time)
                                                                            VALUES (#{username}, #{email}, #{age}, NOW())
                                                                            </insert>
                                                                              </mapper>

10. 最佳实践

  1. 配置文件管理:将数据库连接信息等敏感配置放在外部属性文件中
  2. 结果映射:复杂查询优先使用 resultMap 而非 resultType
  3. 动态 SQL:合理使用动态 SQL 标签提高代码复用性
  4. SQL 片段:将重复的 SQL 片段提取出来使用 sqlinclude 标签
  5. 缓存策略:根据业务需求合理配置缓存策略
  6. 命名规范:遵循统一的命名规范,提高代码可读性

通过合理的 XML 配置,可以充分发挥 MyBatis 的强大功能,构建高效、可维护的数据访问层。

posted @ 2026-01-07 08:11  gccbuaa  阅读(77)  评论(0)    收藏  举报