MyBatis 全局配置文件深度解析:从核心节点到工程实践
MyBatis 全局配置文件(默认命名为 mybatis-config.xml)是 MyBatis 框架的 “总开关”,用于配置数据库连接、映射规则、缓存策略、插件等核心参数。其配置节点有严格的顺序要求(必须按 properties→settings→typeAliases→typeHandlers→objectFactory→plugins→environments→databaseIdProvider→mappers 排列,乱序会导致解析报错),每个节点都承担特定职责。本文将逐一拆解每个节点的核心作用、配置方式、实际应用场景及工程最佳实践,帮助开发者掌握 MyBatis 配置的精髓。
根节点 <configuration>:配置入口
核心作用:作为所有配置节点的父容器,定义 MyBatis 的全局配置上下文。
关键规则:子节点必须按固定顺序排列(MyBatis 解析时会严格校验顺序,顺序错误会抛出
ConfigurationException)。示例结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<configuration>
<!-- 子节点按固定顺序排列 -->
<properties/>
<settings/>
<typeAliases/>
<typeHandlers/>
<objectFactory/>
<plugins/>
<environments/>
<databaseIdProvider/>
<mappers/>
</configuration>
<properties>:属性配置(外部化配置)
核心作用
将数据库连接信息(如 URL、用户名、密码)、环境变量等外部化,避免硬编码在配置文件中,支持动态替换(如开发 / 测试 / 生产环境切换)。
三种配置方式与优先级
MyBatis 加载属性的优先级从低到高如下(高优先级覆盖低优先级):
- 子节点
<property>:直接在<properties>内定义的属性; - 外部配置文件:通过
resource(类路径)或url(网络 / 磁盘路径)引入的.properties文件; - 代码传参:构建
SqlSessionFactory时通过Properties对象传入的参数。
(1)方式 1:子节点 <property> 配置
1 | <properties> |
(2)方式 2:引入外部配置文件(推荐)
外部文件
src/main/resources/jdbc.properties:1
2=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC
=123456MyBatis 配置引用:
1
2
3
4<properties resource="jdbc.properties">
<!-- 子节点属性会被外部文件覆盖(若同名) -->
<property name="jdbc.username" value="dev_root"/> <!-- 最终生效为外部文件的 root -->
</properties>
(3)方式 3:代码传参(优先级最高)
1 | // 构建 SqlSessionFactory 时传入属性,覆盖外部配置 |
3. 高级特性:默认值与分隔符
通过配置属性启用默认值特性,避免因属性缺失导致启动失败:
1 | <properties resource="jdbc.properties"> |
4. 工程实践
Spring Boot 整合:无需单独的jdbc.properties,直接引用application.yml中的配置:
1
2
3
4
5
6
7# application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456MyBatis 可通过
${spring.datasource.url}直接引用 Spring 配置的属性。
<settings>:核心功能开关(重中之重)
<settings> 是 MyBatis 最核心的配置节点,用于覆盖 MyBatis 的默认行为,控制缓存、延迟加载、驼峰映射等关键功能。以下筛选最常用且影响最大的配置项详细说明:
| 配置名 | 核心作用 | 有效值 | 默认值 | 工程建议 |
|---|---|---|---|---|
cacheEnabled |
全局开启 / 关闭二级缓存(一级缓存默认开启,不受此配置影响) | true/false | true | 生产环境建议开启,提升查询性能;高频写场景可关闭 |
lazyLoadingEnabled |
全局开启延迟加载(关联对象(如 User 的 Orders)仅在访问时加载) | true/false | false | 关联查询多的场景(如订单查用户)建议开启,减少冗余加载 |
aggressiveLazyLoading |
开启后,访问任意属性会加载所有延迟关联;关闭后仅按需加载(3.4.1+ 默认 false) | true/false | false(3.4.1+) | 始终关闭,避免加载不必要的关联数据 |
mapUnderscoreToCamelCase |
自动将数据库下划线命名(如 user_name)映射为 Java 驼峰命名(userName) |
true/false | false | 强制开启,减少 resultMap 的配置量 |
logImpl |
指定日志实现(打印 SQL 语句,便于调试) | SLF4J/LOG4J/STDOUT_LOGGING | 未设置 | 开发环境用 STDOUT_LOGGING(控制台打印),生产用 SLF4J(结合 Logback) |
defaultExecutorType |
配置默认执行器(SIMPLE:普通;REUSE:复用 PreparedStatement;BATCH:批量) | SIMPLE/REUSE/BATCH | SIMPLE | 批量插入 / 更新场景用 BATCH,提升性能;普通场景用 SIMPLE |
useGeneratedKeys |
允许 JDBC 自动生成主键(支持 MySQL 自增、Oracle 序列) | true/false | false | 强制开启,配合 keyProperty 获取自增主键(如插入后返回用户 ID) |
配置示例(生产环境常用)
1 | <settings> |
<typeAliases>:类型别名(简化配置)
核心作用
为 Java 类的全类名定义简短别名,在 resultType、parameterType 等配置中替代全类名,减少冗余,提升可读性。
两种配置方式
(1)方式 1:单个类配置(typeAlias)
1 | <typeAliases> |
(2)方式 2:批量包扫描(推荐)
为指定包下的所有类自动生成别名,默认别名为类名首字母小写(如 User → user):
1 | <typeAliases> |
(3)方式 3:注解自定义别名(@Alias)
在 Java 类上用 @Alias 注解自定义别名,优先级高于包扫描的默认规则:
1 | // 注解定义别名,覆盖默认的 "user" |
系统内置别名
MyBatis 为常用 Java 类型预定义了别名(无需配置即可使用),例如:
- 基本类型:
int→_int,long→_long; - 包装类型:
Integer→integer,Long→long; - 集合类型:
List→list,Map→map; - 时间类型:
Date→date,LocalDateTime→localdatetime。
示例:
1 | <!-- 使用内置别名:resultType 为 list(对应 List),泛型为 user --> |
<typeHandlers>:类型处理器(数据类型转换)
核心作用
负责 Java 类型(JavaType) 与 JDBC 类型(JdbcType) 之间的转换:
- 入参转换:将 Java 对象的参数(如
String)转换为 JDBC 支持的类型(如VARCHAR),用于PreparedStatement.setXXX(); - 结果转换:将数据库返回的 JDBC 类型(如
INT)转换为 Java 对象(如Integer),用于ResultSet.getXXX()。
系统内置类型处理器
MyBatis 为绝大多数常用类型提供了默认处理器(无需配置),例如:
StringTypeHandler:String↔VARCHAR;IntegerTypeHandler:Integer↔INTEGER;LocalDateTimeTypeHandler:LocalDateTime↔TIMESTAMP。
自定义类型处理器(实战场景)
当内置处理器无法满足需求时(如枚举、JSON 类型),需自定义处理器。以下以 MySQL JSON 字段映射到 Java Map 为例:
(1)自定义 TypeHandler
1 | import org.apache.ibatis.type.BaseTypeHandler; |
(2)注册自定义处理器
1 | <typeHandlers> |
(3)使用示例
数据库表:
t_user有ext_info字段(类型为 JSON);Mapper XML:
1
2
3
4
5
6
7
8
9
10
11<insert id="insertUser">
INSERT INTO t_user (user_name, ext_info)
VALUES (#{userName}, #{extInfo, typeHandler=com.example.handler.MapJsonTypeHandler})
</insert>
<select id="getUserById" resultType="user">
SELECT id, user_name, ext_info
FROM t_user
WHERE id = #{id}
<!-- 结果自动通过 MapJsonTypeHandler 转换为 Map -->
</select>
<plugins>:插件(扩展 MyBatis 功能)
核心作用
通过拦截 MyBatis 的核心组件(Executor、ParameterHandler、ResultSetHandler、StatementHandler),实现自定义逻辑,如分页、日志、性能监控等。
插件开发原理
插件需实现 org.apache.ibatis.plugin.Interceptor 接口,并通过 @Intercepts 注解指定拦截的组件和方法:
1 | import org.apache.ibatis.executor.Executor; |
注册插件
1 | <plugins> |
常用第三方插件
PageHelper:MyBatis 最流行的分页插件,支持 MySQL、Oracle 等多种数据库的分页查询;
配置示例:
1 | <plugins> |
- MyBatis-Plus:基于 MyBatis 的增强工具,内置分页、CRUD 接口等功能,无需编写 XML。
<environments>:环境配置(多数据源支持)
核心作用
配置数据库连接环境(如开发、测试、生产),每个环境包含 事务管理器 和 数据源 两部分。MyBatis 允许配置多个环境,但每个 SqlSessionFactory 只能选择一个环境。
关键配置项
(1)事务管理器(transactionManager)
MyBatis 提供两种事务管理器:
JDBC:依赖 JDBC 的事务管理(java.sql.Connection的 commit/rollback),适用于独立使用 MyBatis 的场景;MANAGED:依赖外部容器(如 Spring、Java EE)管理事务,MyBatis 不干预事务提交 / 回滚,适用于 Spring 整合场景。
示例:
1 | <transactionManager type="JDBC"/> <!-- 独立使用 MyBatis --> |
(2)数据源(dataSource)
MyBatis 提供三种数据源类型:
| 类型 | 核心特点 | 适用场景 |
|---|---|---|
UNPOOLED |
无连接池,每次请求创建 / 关闭连接 | 开发环境、低并发场景 |
POOLED |
内置连接池,复用连接,提升性能 | 生产环境、中低并发场景 |
JNDI |
从 JNDI 容器获取数据源(如 Tomcat 的数据源) | Java EE 容器环境 |
生产环境推荐:使用第三方连接池(如 Druid、HikariCP)替代 MyBatis 内置数据源,性能更优。以下是整合 Druid 的示例:
引入 Druid 依赖(Maven):
1
2
3
4
5<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.20</version>
</dependency>配置 Druid 数据源:
1
2
3
4
5
6
7
8
9
10
11<dataSource type="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- Druid 连接池参数 -->
<property name="maxActive" value="20"/> <!-- 最大活跃连接数 -->
<property name="minIdle" value="5"/> <!-- 最小空闲连接数 -->
<property name="maxWait" value="60000"/> <!-- 获取连接超时时间(毫秒) -->
<property name="validationQuery" value="SELECT 1"/> <!-- 连接校验 SQL -->
</dataSource>
多环境配置示例
1 | <environments default="development"> |
<databaseIdProvider>:多数据库适配
核心作用
根据数据库厂商(如 MySQL、Oracle)自动选择对应的 SQL 语句,解决多数据库兼容问题(如分页语法差异)。
配置示例
(1)配置数据库标识
1 | <databaseIdProvider type="DB_VENDOR"> |
(2)Mapper XML 中适配多数据库
1 | <!-- MySQL 分页:使用 LIMIT --> |
匹配规则
MyBatis 加载 SQL 语句的优先级:
- 优先加载
databaseId与当前数据库标识一致的语句; - 若未找到,加载无
databaseId的语句; - 若同时存在带
databaseId和不带的语句,不带的会被舍弃。
<mappers>:映射器注册(关联 Mapper 接口与 XML)
核心作用
将 Mapper 接口(如 UserMapper.java)与 SQL 映射文件(如 UserMapper.xml)注册到 MyBatis,确保 MyBatis 能找到并执行 SQL 语句。
四种注册方式
| 方式 | 配置语法 | 注意事项 |
|---|---|---|
| resource | <mapper resource="mapper/UserMapper.xml"/> |
基于类路径(src/main/resources),推荐用于 XML 映射文件;路径用 / 分隔。 |
| url | <mapper url="file:///D:/mapper/UserMapper.xml"/> |
基于磁盘 / 网络路径,需指定完整 URL(如 file:、http:),不推荐工程使用。 |
| class | <mapper class="com.example.mapper.UserMapper"/> |
基于 Mapper 接口: 1. 接口与 XML 需同名且同路径; 2. 若用注解(如 @Select),可无 XML。 |
| package | <package name="com.example.mapper"/> |
批量注册包下所有 Mapper 接口: 1. 接口与 XML 需同名且同路径; 2. 最常用,简化配置。 |
工程实践(Spring Boot 整合)
Spring Boot 中无需在 mybatis-config.xml 中注册 Mapper,直接通过注解扫描:
1 | // 启动类添加 @MapperScan,批量扫描 Mapper 接口 |
常见问题排查
- Mapper 接口未注册:报错No qualifying bean of type ‘com.example.mapper.UserMapper’ available,检查:
@MapperScan扫描路径是否正确;- Mapper 接口是否加了
@Mapper注解(若未用@MapperScan); - 接口与 XML 是否同名且同路径。
总结:全局配置文件工程最佳实践
- 配置顺序不可乱:严格按
properties→settings→typeAliases→...→mappers排列; - 外部化配置优先:数据库信息用外部文件(如
application.yml),避免硬编码; - 关键 settings 必配:
mapUnderscoreToCamelCase、useGeneratedKeys、logImpl等强制开启,提升开发效率; - 批量注册 Mapper:用
<package>或@MapperScan批量注册,减少配置量; - 生产环境用第三方连接池: Druid 或 HikariCP 替代 MyBatis 内置数据源,提升性能;
- 多数据库适配:用
databaseIdProvider解决 SQL 语法差异,避免分支代码
v1.3.10