跳到主要内容

核心配置

MyBatis 的核心配置文件 mybatis-config.xml 包含了影响 MyBatis 行为的各类配置。本章将详细介绍各个配置元素的作用和使用方法。

配置文件结构

MyBatis 配置文件有严格的顺序要求,必须按照以下顺序配置:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
<!-- 1. properties - 属性配置 -->
<properties/>

<!-- 2. settings - 全局设置 -->
<settings/>

<!-- 3. typeAliases - 类型别名 -->
<typeAliases/>

<!-- 4. typeHandlers - 类型处理器 -->
<typeHandlers/>

<!-- 5. objectFactory - 对象工厂 -->
<objectFactory/>

<!-- 6. objectWrapperFactory - 对象包装工厂 -->
<objectWrapperFactory/>

<!-- 7. reflectorFactory - 反射工厂 -->
<reflectorFactory/>

<!-- 8. plugins - 插件 -->
<plugins/>

<!-- 9. environments - 环境配置 -->
<environments/>

<!-- 10. databaseIdProvider - 数据库厂商标识 -->
<databaseIdProvider/>

<!-- 11. mappers - 映射器 -->
<mappers/>
</configuration>

properties 元素

properties 元素用于外部化配置,可以从属性文件或子元素中加载配置值。

从属性文件加载

# db.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_demo
jdbc.username=root
jdbc.password=123456
<configuration>
<properties resource="db.properties"/>

<environments default="development">
<environment id="development">
<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>
</configuration>

从子元素配置

<properties>
<property name="jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis_demo"/>
</properties>

优先级

当同一属性在多处定义时,优先级从高到低:

  1. 方法参数传递的属性
  2. resource/url 加载的属性
  3. properties 元素内的 property 子元素

默认值支持

从 MyBatis 3.4.2 开始,可以为占位符指定默认值:

<dataSource type="POOLED">
<!-- 如果属性 'username' 没有被配置,将使用默认值 'ut_user' -->
<property name="username" value="${username:ut_user}"/>
</dataSource>

启用默认值特性:

<properties resource="org/mybatis/example/config.properties">
<property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
</properties>

settings 元素

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

常用设置项

<settings>
<!-- 开启驼峰命名自动映射 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>

<!-- 开启全局二级缓存 -->
<setting name="cacheEnabled" value="true"/>

<!-- 延迟加载全局开关 -->
<setting name="lazyLoadingEnabled" value="true"/>

<!-- 积极加载(false 按需加载) -->
<setting name="aggressiveLazyLoading" value="false"/>

<!-- 允许 JDBC 支持自动生成主键 -->
<setting name="useGeneratedKeys" value="true"/>

<!-- 使用列标签代替列名 -->
<setting name="useColumnLabel" value="true"/>

<!-- 开启自动映射 -->
<setting name="autoMappingBehavior" value="PARTIAL"/>

<!-- 配置默认的执行器 -->
<setting name="defaultExecutorType" value="SIMPLE"/>

<!-- 设置超时时间 -->
<setting name="defaultStatementTimeout" value="25"/>

<!-- 本地缓存作用域 -->
<setting name="localCacheScope" value="SESSION"/>

<!-- 当没有为参数指定 JDBC 类型时,空值的默认 JDBC 类型 -->
<setting name="jdbcTypeForNull" value="OTHER"/>

<!-- 指定触发延迟加载的方法 -->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

设置项详解

设置名说明默认值
cacheEnabled全局开启二级缓存true
lazyLoadingEnabled延迟加载开关false
aggressiveLazyLoading积极加载(任一方法调用加载所有延迟属性)false (3.4.1+)
multipleResultSetsEnabled允许单条语句返回多结果集true
useColumnLabel使用列标签代替列名true
useGeneratedKeys允许 JDBC 自动生成主键false
autoMappingBehavior自动映射行为(NONE/PARTIAL/FULL)PARTIAL
autoMappingUnknownColumnBehavior自动映射未知列行为(NONE/WARNING/FAILING)NONE
defaultExecutorType默认执行器(SIMPLE/REUSE/BATCH)SIMPLE
defaultStatementTimeout超时时间(秒)null
defaultFetchSize获取数量null
defaultResultSetType语句默认滚动策略(3.5.2+)null
safeRowBoundsEnabled允许在嵌套语句中使用分页false
safeResultHandlerEnabled允许在嵌套语句中使用结果处理器true
mapUnderscoreToCamelCase驼峰命名映射(a_column -> aColumn)false
localCacheScope本地缓存作用域(SESSION/STATEMENT)SESSION
jdbcTypeForNull空值 JDBC 类型OTHER
lazyLoadTriggerMethods延迟加载触发方法equals,clone,hashCode,toString
defaultScriptingLanguage动态 SQL 生成使用的默认脚本语言XMLLanguageDriver
defaultEnumTypeHandlerEnum 使用的默认 TypeHandler(3.4.5+)EnumTypeHandler
callSettersOnNulls空值调用 setterfalse
returnInstanceForEmptyRow空行返回实例(而非 null)(3.4.2+)false
logPrefix日志前缀null
logImpl日志实现(SLF4J/LOG4J2/JDK_LOGGING等)null
proxyFactory延迟加载对象代理工具(JAVASSIST)JAVASSIST
vfsImplVFS 实现类null
useActualParamName使用方法签名中的名称作为参数名(3.4.1+,需 Java 8 + -parameterstrue
configurationFactory提供 Configuration 实例的类(3.2.3+)null
shrinkWhitespacesInSql从 SQL 中删除多余空格(3.5.5+)false
defaultSqlProviderType默认的 sql provider 类(3.5.6+)null
nullableOnForEachforeach 标签 nullable 属性默认值(3.5.9+)false
argNameBasedConstructorAutoMapping构造器自动映射使用参数名搜索列(3.5.10+)false

执行器类型

  • SIMPLE:普通执行器,每次执行创建新的 Statement
  • REUSE:重用执行器,会重用 Statement
  • BATCH:批量执行器,重用 Statement 并批量执行

关键设置项详解

defaultResultSetType(3.5.2+)

指定语句默认的滚动策略,用于控制结果集的滚动方式:

<settings>
<!-- 可选值:FORWARD_ONLY, SCROLL_SENSITIVE, SCROLL_INSENSITIVE, DEFAULT -->
<setting name="defaultResultSetType" value="SCROLL_SENSITIVE"/>
</settings>
  • FORWARD_ONLY:只能向前滚动(默认 JDBC 行为)
  • SCROLL_SENSITIVE:可滚动且对数据变化敏感
  • SCROLL_INSENSITIVE:可滚动但对数据变化不敏感
  • DEFAULT:等同于未设置

defaultEnumTypeHandler(3.4.5+)

指定枚举类型默认的类型处理器:

<settings>
<!-- 使用枚举名称存储 -->
<setting name="defaultEnumTypeHandler" value="org.apache.ibatis.type.EnumTypeHandler"/>

<!-- 或者使用枚举序号存储 -->
<setting name="defaultEnumTypeHandler" value="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
</settings>

两种处理器的区别:

处理器存储方式示例
EnumTypeHandler枚举名称字符串ENABLED -> "ENABLED"
EnumOrdinalTypeHandler枚举序号ENABLED -> 1

useActualParamName(3.4.1+)

允许使用方法签名中的名称作为语句参数名称:

// 启用后可以直接使用参数名
@Select("SELECT * FROM user WHERE username = #{username} AND status = #{status}")
User selectByUsernameAndStatus(String username, Integer status);

// 不需要再使用 @Param 注解(但多参数时仍建议使用)

启用条件

  • Java 8 及以上版本
  • 编译时添加 -parameters 选项

Maven 配置

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>

shrinkWhitespacesInSql(3.5.5+)

从 SQL 中删除多余的空格字符:

<settings>
<setting name="shrinkWhitespacesInSql" value="true"/>
</settings>

效果对比

-- 原始 SQL(动态生成后)
SELECT * FROM user WHERE id = 1

-- 启用后
SELECT * FROM user WHERE id = 1

注意:此设置也会影响 SQL 中的字符串字面量,可能改变字符串内容。

argNameBasedConstructorAutoMapping(3.5.10+)

构造器自动映射时使用参数名称搜索列,而非依赖列顺序:

public class User {
private final Long id;
private final String username;

// 构造器参数名与列名匹配
public User(Long id, String username) {
this.id = id;
this.username = username;
}
}
<settings>
<!-- 启用后,构造器参数名会与列名匹配 -->
<setting name="argNameBasedConstructorAutoMapping" value="true"/>
</settings>

好处:当数据库列顺序与构造器参数顺序不一致时,仍能正确映射。

configurationFactory(3.2.3+)

提供一个用于加载被反序列化对象延迟加载属性值的 Configuration 实例:

public class ConfigurationFactory {
private static Configuration configuration;

public static Configuration getConfiguration() {
return configuration;
}

public static void setConfiguration(Configuration config) {
configuration = config;
}
}
<settings>
<setting name="configurationFactory" value="com.example.ConfigurationFactory"/>
</settings>

应用场景:当对象被序列化后再反序列化,需要重新获取 Configuration 来完成延迟加载。

typeAliases 元素

类型别名是为 Java 类型设置一个缩写名字,减少类全限定名的冗余。

配置方式

<typeAliases>
<!-- 单个别名配置 -->
<typeAlias type="com.example.mybatis.entity.User" alias="User"/>

<!-- 包扫描配置(推荐) -->
<package name="com.example.mybatis.entity"/>
</typeAliases>

使用注解配置别名

@Alias("user")
public class User {
// ...
}

内置类型别名

MyBatis 为常见的 Java 类型内置了别名:

别名映射类型说明
_bytebyte原始类型
_charchar原始类型(3.5.10+)
_characterchar原始类型(3.5.10+)
_longlong原始类型
_shortshort原始类型
_intint原始类型
_integerint原始类型
_doubledouble原始类型
_floatfloat原始类型
_booleanboolean原始类型
stringString字符串
byteByte包装类型
charCharacter包装类型(3.5.10+)
characterCharacter包装类型(3.5.10+)
longLong包装类型
shortShort包装类型
intInteger包装类型
integerInteger包装类型
doubleDouble包装类型
floatFloat包装类型
booleanBoolean包装类型
dateDate日期类型
decimalBigDecimal大数字
bigdecimalBigDecimal大数字
bigintegerBigInteger大整数
objectObject对象
date[]Date[]日期数组
decimal[]BigDecimal[]大数字数组
bigdecimal[]BigDecimal[]大数字数组
biginteger[]BigInteger[]大整数数组
object[]Object[]对象数组
mapMap映射
hashmapHashMap哈希映射
listList列表
arraylistArrayList数组列表
collectionCollection集合
iteratorIterator迭代器

typeHandlers 元素

类型处理器用于 Java 类型与 JDBC 类型之间的转换。

内置类型处理器

MyBatis 内置了大量的类型处理器:

类型处理器Java 类型JDBC 类型
BooleanTypeHandlerBooleanBOOLEAN
ByteTypeHandlerByteNUMERIC/SMALLINT
ShortTypeHandlerShortNUMERIC/SMALLINT
IntegerTypeHandlerIntegerNUMERIC/INTEGER
LongTypeHandlerLongNUMERIC/BIGINT
FloatTypeHandlerFloatNUMERIC/FLOAT
DoubleTypeHandlerDoubleNUMERIC/DOUBLE
StringTypeHandlerStringCHAR/VARCHAR
DateTypeHandlerDateTIMESTAMP
LocalDateTimeTypeHandlerLocalDateTimeTIMESTAMP
LocalDateTypeHandlerLocalDateDATE
LocalTimeTypeHandlerLocalTimeTIME

自定义类型处理器

当内置处理器不能满足需求时,可以自定义:

@MappedTypes(String.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ExampleTypeHandler extends BaseTypeHandler<String> {

@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, parameter);
}

@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getString(columnName);
}

@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return rs.getString(columnIndex);
}

@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return cs.getString(columnIndex);
}
}

配置自定义类型处理器:

<typeHandlers>
<typeHandler handler="com.example.mybatis.handler.ExampleTypeHandler"/>

<!-- 或者包扫描 -->
<package name="com.example.mybatis.handler"/>
</typeHandlers>

枚举类型处理器

MyBatis 提供了两种枚举处理器:

public enum Status {
ENABLED(1, "启用"),
DISABLED(0, "禁用");

private final int code;
private final String desc;

Status(int code, String desc) {
this.code = code;
this.desc = desc;
}

public int getCode() { return code; }
public String getDesc() { return desc; }
}
<!-- 使用序号存储 -->
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
javaType="com.example.mybatis.enums.Status"/>

<!-- 使用名称存储 -->
<typeHandler handler="org.apache.ibatis.type.EnumTypeHandler"
javaType="com.example.mybatis.enums.Status"/>

objectFactory 元素

ObjectFactory(对象工厂)负责创建结果对象实例。MyBatis 每次创建结果对象时都会使用 ObjectFactory。默认的 ObjectFactory 只是通过无参构造器或带参数的构造器创建对象。

默认行为

默认的 ObjectFactory 行为:

  1. 使用无参构造器创建对象
  2. 如果存在参数映射,使用带参构造器
  3. 支持注入属性值

自定义 ObjectFactory

当默认的对象创建逻辑不能满足需求时,可以自定义 ObjectFactory:

public class CustomObjectFactory extends DefaultObjectFactory {

@Override
public <T> T create(Class<T> type) {
return super.create(type);
}

@Override
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
return super.create(type, constructorArgTypes, constructorArgs);
}

@Override
public void setProperties(Properties properties) {
super.setProperties(properties);
}

@Override
public <T> boolean isCollection(Class<T> type) {
return Collection.class.isAssignableFrom(type);
}
}

配置 ObjectFactory

<objectFactory type="com.example.mybatis.factory.CustomObjectFactory">
<property name="someProperty" value="100"/>
</objectFactory>

ObjectFactory 接口方法

方法说明
create(Class<T> type)通过无参构造器创建对象
create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs)通过带参构造器创建对象
setProperties(Properties properties)设置配置属性
isCollection(Class<T> type)判断类型是否为集合

应用场景

自定义 ObjectFactory 的典型应用场景:

  1. 依赖注入:创建对象时自动注入依赖
  2. 对象池:复用对象,减少 GC 压力
  3. 代理对象:返回代理对象而非真实对象
  4. 初始化逻辑:对象创建后执行初始化逻辑

与 Spring 整合时的注意点

当与 Spring 整合时,通常不需要自定义 ObjectFactory,因为 Spring 会管理 Bean 的生命周期。MyBatis-Spring 会自动处理对象的创建和依赖注入。

plugins 元素

MyBatis 允许在映射语句执行过程中的某一点进行拦截调用。

可拦截的方法

自定义插件示例

@Intercepts({
@Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
)
})
public class ExamplePlugin implements Interceptor {

@Override
public Object intercept(Invocation invocation) throws Throwable {
// 前置处理
long start = System.currentTimeMillis();

// 执行原方法
Object result = invocation.proceed();

// 后置处理
long end = System.currentTimeMillis();
System.out.println("SQL 执行耗时: " + (end - start) + "ms");

return result;
}

@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}

@Override
public void setProperties(Properties properties) {
// 设置属性
}
}

配置插件:

<plugins>
<plugin interceptor="com.example.mybatis.plugin.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>

environments 元素

MyBatis 可以配置多种环境,每个环境对应一个数据库配置。

多环境配置

<environments default="development">
<!-- 开发环境 -->
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${dev.driver}"/>
<property name="url" value="${dev.url}"/>
<property name="username" value="${dev.username}"/>
<property name="password" value="${dev.password}"/>
</dataSource>
</environment>

<!-- 测试环境 -->
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${test.driver}"/>
<property name="url" value="${test.url}"/>
<property name="username" value="${test.username}"/>
<property name="password" value="${test.password}"/>
</dataSource>
</environment>

<!-- 生产环境 -->
<environment id="production">
<transactionManager type="MANAGED"/>
<dataSource type="JNDI">
<property name="data_source" value="java:comp/env/jdbc/MyDataSource"/>
</dataSource>
</environment>
</environments>

事务管理器

类型说明
JDBC使用 JDBC 的提交和回滚设置,依赖从数据源获取的连接来管理事务
MANAGED让容器来管理事务的整个生命周期,默认情况下会关闭连接

数据源类型

类型说明
UNPOOLED每次请求时打开和关闭连接,不使用连接池
POOLED使用连接池,复用连接,提高性能
JNDI通过 JNDI 获取数据源,用于 EJB 或应用服务器

POOLED 数据源配置

<dataSource type="POOLED">
<!-- 基础配置 -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>

<!-- 连接池配置 -->
<property name="poolMaximumActiveConnections" value="10"/>
<property name="poolMaximumIdleConnections" value="5"/>
<property name="poolMaximumCheckoutTime" value="20000"/>
<property name="poolTimeToWait" value="20000"/>
<property name="poolPingQuery" value="SELECT 1"/>
<property name="poolPingEnabled" value="true"/>
<property name="poolPingConnectionsNotUsedFor" value="3600000"/>
</dataSource>
属性说明默认值
poolMaximumActiveConnections最大活动连接数10
poolMaximumIdleConnections最大空闲连接数5
poolMaximumCheckoutTime获取连接最长等待时间20000ms
poolTimeToWait等待获取连接的时间20000ms
poolPingQuery检测连接是否有效的 SQL
poolPingEnabled是否启用连接检测false
poolPingConnectionsNotUsedFor检测间隔时间0

databaseIdProvider 元素

用于支持多数据库厂商,根据不同数据库执行不同的 SQL。

配置

<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver"/>
<property name="DB2" value="db2"/>
<property name="Oracle" value="oracle"/>
<property name="MySQL" value="mysql"/>
<property name="PostgreSQL" value="postgresql"/>
</databaseIdProvider>

使用

<select id="selectById" resultType="User" databaseId="mysql">
SELECT * FROM user WHERE id = #{id}
</select>

<select id="selectById" resultType="User" databaseId="oracle">
SELECT * FROM user WHERE id = #{id}
</select>

mappers 元素

告诉 MyBatis 到哪里去找映射文件。

配置方式

<mappers>
<!-- 使用相对于类路径的资源引用 -->
<mapper resource="com/example/mybatis/mapper/UserMapper.xml"/>

<!-- 使用完全限定资源定位符(URL) -->
<mapper url="file:///var/mappers/UserMapper.xml"/>

<!-- 使用映射器接口实现类的完全限定类名 -->
<mapper class="com.example.mybatis.mapper.UserMapper"/>

<!-- 将包内的映射器接口实现全部注册为映射器 -->
<package name="com.example.mybatis.mapper"/>
</mappers>

推荐配置

使用包扫描方式最简洁:

<mappers>
<package name="com.example.mybatis.mapper"/>
</mappers>

注意:使用包扫描时,XML 文件必须与接口在同一包路径下。

完整配置示例

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
<!-- 属性配置 -->
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>

<!-- 全局设置 -->
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="useGeneratedKeys" value="true"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="30"/>
<setting name="logImpl" value="SLF4J"/>
</settings>

<!-- 类型别名 -->
<typeAliases>
<package name="com.example.mybatis.entity"/>
</typeAliases>

<!-- 类型处理器 -->
<typeHandlers>
<package name="com.example.mybatis.handler"/>
</typeHandlers>

<!-- 插件 -->
<plugins>
<plugin interceptor="com.example.mybatis.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}"/>
<property name="poolMaximumActiveConnections" value="20"/>
<property name="poolPingEnabled" value="true"/>
</dataSource>
</environment>
</environments>

<!-- 数据库厂商标识 -->
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/>
</databaseIdProvider>

<!-- 映射器 -->
<mappers>
<package name="com.example.mybatis.mapper"/>
</mappers>
</configuration>

小结

本章详细介绍了 MyBatis 核心配置文件的各个元素:

  • properties:外部化配置管理
  • settings:全局行为设置
  • typeAliases:类型别名简化
  • typeHandlers:类型转换处理
  • plugins:插件扩展机制
  • environments:多环境配置
  • databaseIdProvider:多数据库支持
  • mappers:映射器注册

下一章将介绍 XML 映射器的详细用法。