前言
MyBatis 的 XML 配置文件 mybatis-config.xml
其实并不复杂,基本上参考官方文档即可完成。
配置
不是所有的配置都需要去设置(有默认值),也不是所有的配置我都懂得去设置(限于技术水平),配置文件中的对象工厂(objectFactory)、插件(plugins)不进行介绍。
标签顺序
根据官方文档,配置文档的顶层结构如下:
configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
这个结构顺序恰好对应配置标签的顺序,顺序不能乱,否则 IDEA 将提示以下错误:
The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)".
properties
properties 属性可以给系统配置一些运行参数,可以放在 XML 文件或 properties 文件中。例如:
<!-- 导入外部配置文件 -->
<properties resource="config/mysql.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
设置好的属性可以在整个配置文件中用来替换需要动态配置的属性值。例如:
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
这个例子中的所有属性将会由 mysql.properties 文件中对应的值来替换。虽然在 properties 元素也设置了 username
和 password
的值,但是要注意 MyBatis 的加载顺序:
- 首先读取在 properties 元素体内指定的属性。
- 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
- 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。
settings
settings 是 MyBatis 中最复杂的配置,它能深刻的影响 MyBatis 底层的运行,但是在大部分情况下,使用默认值运行即可。
官方提供的一个配置完整的 settings 元素的示例如下:
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
这里介绍几个常见的设置:
<!-- 配置 settings -->
<settings>
<!-- 全局性地开启缓存 -->
<setting name="cacheEnabled" value="true"/>
<!-- 延迟加载的全局开关 -->
<setting name="lazyLoadingEnabled" value="false"/>
<!-- 允许 JDBC 支持自动生成主键 -->
<setting name="useGeneratedKeys" value="true"/>
<!-- 开启驼峰命名自动映射 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 指定日志的具体实现:STDOUT_LOGGING 标准日志输出 -->
<setting name="logImpl" value="LOG4J"/>
</settings>
别忘了,在指定 MyBatis 所用日志的具体实现之前,导入所需要的日志依赖。
typeAliases
它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
<typeAliases>
<typeAlias alias="User" type="top.yyt.entity.User"/>
</typeAliases>
当这样配置时,User
可以用在任何使用 top.yyt.entity.User
的地方,例如用在映射文件 mapper.xml 中的 resultType
属性。
但是开发中肯定存在大量的实体类,一个一个的配置别名就很繁琐了。因此 MyBatis 还提供了扫描包的方式:指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:
<typeAliases>
<package name="top.yyt.entity"/>
</typeAliases>
每一个在包 top.yyt.entity
中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。若使用注解 @Alias
去设置别名,则别名为其注解值。
typeHandlers
在 JDBC 中,需要在预处理语句 PreparedStatement 中设置哪些已经预编译过的 SQL 语句的参数。执行 SQL 后,会通过 ResultSet 对象获取得到数据库的数据。而 TypeHandler 正是用于 JavaType 与 JdbcType 之间的转换。
MyBatis 默认提供了很多类型处理器,你可以重写已有的类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。具体做法为:实现 org.apache.ibatis.type.TypeHandler
接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler
, 并且可以(可选地)将它映射到一个 JDBC 类型。
这里简单演示一下把 MySQL 的 DECIMAL 类型转换为 Java 的 String 类型。通过类型处理器的泛型,MyBatis 可以得知该类型处理器处理的 Java 类型。
@MappedTypes(String.class)
@MappedJdbcTypes(JdbcType.DECIMAL)
public class ExampleTypeHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String s, JdbcType jdbcType) throws SQLException {
ps.setString(i, s);
}
@Override
public String getNullableResult(ResultSet rs, String s) throws SQLException {
return rs.getString(s);
}
@Override
public String getNullableResult(ResultSet rs, int i) throws SQLException {
return rs.getString(i);
}
@Override
public String getNullableResult(CallableStatement cs, int i) throws SQLException {
return cs.getString(i);
}
}
然后在 mybatis-config.xml
中配置:
<!-- 配置类型处理器 -->
<typeHandlers>
<typeHandler handler="top.yyt.utils.ExampleTypeHandler"/>
</typeHandlers>
还需要在 mapper.xml 中显式地设置 TypeHandler,否则类型处理器在 ResultMap 中将不会生效。
<!-- 结果映射 -->
<resultMap id="userMap" type="user">
<!-- property 是实体类的属性名,column 是数据表中的字段名 -->
<id property="id" column="id"/>
<!-- 如果都一致,就没必要写了,只需要映射不一致的 -->
<result property="name" column="name"/>
<result property="pwd" column="pwd"/>
<result property="money" column="money" typeHandler="top.yyt.utils.ExampleTypeHandler"/>
</resultMap>
由于有时候自定义的类型转换器会比较多,可以考虑使用扫描包的方式让 MyBatis 帮你查找类型处理器。注意:在使用自动发现功能的时候,只能通过注解方式来指定 JDBC 的类型。
<typeHandlers>
<package name="top.yyt.utils"/>
</typeHandlers>
environments
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中,现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置。
<!-- 配置环境 -->
<environments default="development">
<!-- 开发环境 -->
<environment id="development">
<!-- 事务管理器 -->
<transactionManager type="JDBC"/>
<!-- 属性将会由 mysql.properties 文件中对应的值来替换 -->
<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>
<!-- 测试环境 -->
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver2}"/>
<property name="url" value="${url2}"/>
<property name="username" value="${username2}"/>
<property name="password" value="${password2}"/>
</dataSource>
</environment>
</environments>
databaseIdProvider
databaseIdProvider 元素主要是为了支持不同厂商的数据库,MyBatis 可以根据不同的数据库厂商执行不同的语句。配置如下:
<!-- 配置数据库厂商标识 -->
<databaseIdProvider type="DB_VENDOR">
<!-- name 属性是数据库名称,value 是我们自定义的别名 -->
<property name="SQL Server" value="sqlserver"/>
<property name="MySQL" value="mysql"/>
<property name="DB2" value="db2"/>
<property name="Oracle" value="oracle" />
</databaseIdProvider>
在映射文件 mapper.xml 中需要指定 SQL 语句对应的 databaseId 属性:databaseId 属性的值与全局配置中 databaseIdProvider 子标签的 value 值对应。
<insert id="addUser" parameterType="user" databaseId="mysql">
insert into user(name, pwd, money)
VALUES (#{name}, #{pwd}, #{money});
</insert>
mappers
这些配置会告诉 MyBatis 去哪里找映射文件。
<!-- mappers:映射器,告诉 MyBatis 到哪里去找映射文件 -->
<mappers>
<!-- 方式1:使用相对于类路径的资源引用 -->
<!-- <mapper resource="top/yyt/mapper/UserMapper.xml"/>-->
<!-- 方式2:使用映射器接口实现类的完全限定类名 -->
<!-- <mapper class="top.yyt.mapper.UserMapper"/>-->
<!-- 方式3:将包内的映射器接口实现全部注册为映射器,省事 -->
<package name="top.yyt.mapper"/>
</mappers>
参考
简书
CSDN
https://q1.qlogo.cn/g?b=qq&nk=1351856278&s=100