Mybatis配置文件是MyBatis框架运行的基石,它集中管理了数据库连接、全局参数、映射文件路径等所有关键信息,一次配置,全程生效,深入理解其每个标签的用途和配置顺序,是解决绝大多数启动报错和运行时异常的前提。
配置文件里到底藏着什么:全局配置项一览
很多初学者把MyBatis配置文件当成一个”复制粘贴”的模板,报错了就百度,从没仔细看过每个标签实际管控的范围,其实这份XML文件就是MyBatis框架的大管家,所有SQL执行前的参数准备都在这里完成。
从整体结构来看,核心配置文件(通常命名为mybatis-config.xml)由以下部分组成,配置顺序有严格要求,放错位置会直接导致启动失败:
- properties:读取外部properties文件,实现动态参数替换。
- settings:全局行为开关,比如驼峰命名映射、二级缓存开关。
- typeAliases:为Java类型取别名,让Mapper XML里的resultType更简短。
- typeHandlers:处理Java类型与JDBC类型之间的转换。
- objectFactory:创建结果对象实例的工厂,一般很少动。
- plugins(即拦截器):允许你拦截SQL执行过程中的关键方法。
- environments:配置数据源和事务管理器,支持多环境切换。
- databaseIdProvider:支持多数据库厂商适配。
- mappers:注册Mapper映射文件或Mapper接口。
这些标签在mybatis配置文件参数里各有分工,但日常开发中我们接触最多的是settings、environments和mappers,接下来拆开细聊。
settings参数详解:全局行为的总开关
settings标签里罗列了几乎所有MyBatis的运行时行为参数,它就像操作系统的控制面板,调错一项,可能不影响启动,但运行时的bug会让你怀疑人生。
高频必配参数
- mapUnderscoreToCamelCase:设为true后,数据库字段user_name自动映射到Java属性userName,省去写大量resultMap的麻烦。哪个项目中没配它,开发时手动封装结果集就会特别痛苦。
- logImpl:指定日志实现,可选值有SLF4J、LOG4J2、STDOUT_LOGGING等,配成STDOUT_LOGGING可以无依赖地在控制台打印SQL,本地调试特别实用。
- cacheEnabled:全局二级缓存总开关,默认true,如果不用缓存,建议显式设为false,避免数据一致性问题。
- lazyLoadingEnabled:延迟加载全局开关,配合association和collection使用,在查询主表时不立即加载关联对象。
- aggressiveLazyLoading:设为false才能让延迟加载真正生效,否则遇到对象属性访问还是会立即触发全量查询。

<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="cacheEnabled" value="false"/>
</settings>
业内专家指出,绝大多数公司内部代码规范会强制要求开启mapUnderscoreToCamelCase,这已经成为行业基本共识。
性能与调试相关的参数
- defaultExecutorType:默认SIMPLE,还有REUSE和BATCH,批处理场景下很值得改成BATCH,性能提升非常明显,但SQL语句不能复用。
- localCacheScope:默认为SESSION,同一个会话中重复查询走本地缓存,但并发场景下可能读到脏值,许多高并发项目会设为STATEMENT。
核心配置文件中标签顺序为什么要严格
MyBatis的XML Schema(XSD)规定了所有标签的出现顺序,在配置文件中放置错误会启动直接报错:The content of element type “configuration” must match…。
正确顺序是:properties → settings → typeAliases → typeHandlers → objectFactory → objectWrapperFactory → reflectorFactory → plugins → environments → databaseIdProvider → mappers。
从实际项目复盘来看,新手写配置时最容易犯的错是把environments写在settings之前,或者把mappers放在最上面,这个问题出现的频率在”mybatis启动报错”相关搜索里长期排在前几位。
<configuration>
<!-- 正确顺序示范 -->
<properties resource="db.properties"/>
<settings>...</settings>
<typeAliases>...</typeAliases>
<environments default="development">...</environments>
<mappers>...</mappers>
</configuration>

environments配置:开发、测试、生产环境一键切换
environments标签解决的核心问题是环境隔离,它可以同时定义多套环境,通过default属性指定当前生效环境(如development、test、production,依据各团队规范命名各环境环境变量),切换环境时完全不用改动代码。
每个environment内部由transactionManager(事务管理器)和dataSource(数据源)构成:
- transactionManager:JDBC类型直接使用JDBC的commit和rollback;MANAGED类型会把事务交给外部容器管理,在Spring集成项目里Spring接管事务,MyBatis这里配JDBC即可。
- dataSource:最常用的是POOLED(连接池复用),其次是UNPOOLED(每次请求新建连接),JNDI类型适合部署在Tomcat等Web容器中的场景。
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
使用连接池时,POOLED自带的连接复用机制能有效减少连接创建开销,若项目迁移到了Spring Boot中,数据源配置会移到application.yml里,此时MyBatis配置文件中的environments标签会整体移除。
mappers标签的三种注册方式
mappers标签负责告诉MyBatis去哪里寻找SQL映射。这个标签没配好,即使DAO接口写得再漂亮,运行时的SQL就是执行不到。
常用方式有三种:
- resource方式:指向classpath下的Mapper.xml文件,最通用,不会暴露接口实现内部结构,拆分多个映射文件时非常清晰。
- class方式:直接指定Mapper接口的全限定名,要求接口和XML文件同包同名,否则无法自动关联。
- url方式:使用本地文件系统路径,一般只在脱离classpath的特殊场景(比如读取服务器特定位置的XML)才会用到。

<mappers>
<mapper resource="com/example/mapper/UserMapper.xml"/>
<mapper resource="com/example/mapper/OrderMapper.xml"/>
</mappers>
很多人在Spring项目中跑了几个月都没发现,mapper接口扫描通过@MapperScan完成之后,MyBatis配置文件中的mappers其实可以留空,两者选一种即可。
typeAliases别名机制:让XML少写半包名
在resultType中写全限定类名非常冗长,typeAliases的作用就是给实体类起短发名称,核心配置文件参数里声明了这个标签后,XML中即可直接使用类名(不区分大小写)代替全路径。
<typeAliases>
<package name="com.example.entity"/>
</typeAliases>
使用package方式批量扫描包下所有类,别名默认为类名首字母小写;使用typeAlias单独定义别名,可控性更强,但数量多时配置会更繁琐,需要合理取舍,Java内置的常用类型如int、list、map,MyBatis原生就已经提供了内置别名,不用重复定义。
Q&A:mybatis配置文件常见问题排查
配置文件放在classpath根目录下没生效,是什么原因?
MyBatis默认加载路径是类路径classpath,标准Maven项目中应将mybatis-config.xml放在src/main/resources目录下,如果放在src/main/java里,构建时不一定被复制到target/classpath中,会导致”找不到配置文件”的启动报错。
映射文件里的参数占位符#{}和${}有什么区别?在配置文件中能控制吗?
{}是预编译占位符,对应JDBC的PreparedStatement,能有效防止SQL注入;${}是字符串直接拼接,普通查询场景不建议使用,二者选择更多取决于SQL写法,无法在全局限参数中直接改写,任何配置项都不能把${}变成#{},唯一能间接影响的是settings相关SQL方言,比如开启驼峰映射能改善结果集的字段映射。
改了settings参数后,为什么SQL执行结果没变化?
确认项目是否属于热部署场景,如对resources目录的改动未触发重新加载;或者当前项目同时存在Spring容器中的配置覆盖了全局配置,排查Spring配置中是否重复定义属性,确认当前配置文件的优先级和生效路径。
