跳到主要内容

核心配置

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 子元素

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="safeRowBoundsEnabled" value="false"/>

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

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

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

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

设置项详解

设置项说明默认值可选值
cacheEnabled全局开启二级缓存truetrue/false
lazyLoadingEnabled延迟加载开关falsetrue/false
aggressiveLazyLoading积极加载false (3.4.1+)true/false
multipleResultSetsEnabled允许单条语句返回多结果集truetrue/false
useColumnLabel使用列标签代替列名truetrue/false
useGeneratedKeys允许 JDBC 自动生成主键falsetrue/false
autoMappingBehavior自动映射行为PARTIALNONE/PARTIAL/FULL
autoMappingUnknownColumnBehavior自动映射未知列行为NONENONE/WARNING/FAILING
defaultExecutorType默认执行器SIMPLESIMPLE/REUSE/BATCH
defaultStatementTimeout超时时间null正整数
defaultFetchSize获取数量null正整数
defaultResultSetType结果集类型nullFORWARD_ONLY/SCROLL_SENSITIVE/SCROLL_INSENSITIVE
safeRowBoundsEnabled允许嵌套语句分页falsetrue/false
safeResultHandlerEnabled允许嵌套语句结果处理truetrue/false
mapUnderscoreToCamelCase驼峰命名映射falsetrue/false
localCacheScope本地缓存作用域SESSIONSESSION/STATEMENT
jdbcTypeForNull空值 JDBC 类型OTHERNULL/VARCHAR/OTHER
lazyLoadTriggerMethods延迟加载触发方法equals,clone,hashCode,toString方法名列表
callSettersOnNulls空值调用 setterfalsetrue/false
returnInstanceForEmptyRow空行返回实例falsetrue/false
logPrefix日志前缀null字符串
logImpl日志实现nullSLF4J/LOG4J/LOG4J2/JDK_LOGGING/COMMONS_LOGGING/STDOUT_LOGGING/NO_LOGGING
proxyFactory代理工厂JAVASSISTCGLIB/JAVASSIST
vfsImplVFS 实现null类全限定名
useActualParamName使用实际参数名truetrue/false
configurationFactory配置工厂null类全限定名

执行器类型

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

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
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
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"/>

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 映射器的详细用法。