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>
<!-- 环境变量列表 -->
<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>
<!-- mapper 映射文件列表 -->
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
- 根节点是 configuration(所有配置信息都会保存在一个 configuration 对象中)
- 可以有多个环境变量配置,意味着支持多数据源
- 示例没有写完所有配置,还有别的比如 属性、别名、插件 等等
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
properties
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 定义 properties -->
<properties>
<property name="jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/test" />
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="root"/>
</properties>
...
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 这里能用已定义的 properties -->
<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>
对于关键信息配置,常见做法是独立一个配置文件,通过 resource 引入这个配置文件,如: <properties resource="org/mybatis/example/config.properties" />
settings
<settings>
<!-- 缓存开关(二级缓存) -->
<setting name="cacheEnabled" value="true"/>
<!-- 一级缓存 -->
<setting name="localCacheScope" value="SESSION"/>
<!-- 懒加载配置 -->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="true"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
<!-- 自动映射配置 -->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<!-- 日志配置,STDOUT_LOGGING -->
<setting name="logPrefix" value="exampleLogPreFix_"/>
<setting name="logImpl" value="SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING"/>
<!-- 查询结果为空时,默认是直接返回 null,如果配置成 true 会返回一个空对象(对象不为空,所有属性没有值)-->
<setting name="returnInstanceForEmptyRow" value="false"/>
<!-- 字段为空是否映射到实体属性(调用 setter,如果是 map 就是 put 方法)对 map 有影响-->
<setting name="callSettersOnNulls" value="false"/>
<!-- 是否允许单一语句返回多结果集,这个不用想肯定要打开 -->
<setting name="multipleResultSetsEnabled" value="true"/>
<!-- 使用列标签代替列名 -->
<setting name="useColumnLabel" value="true"/>
<!-- 允许 JDBC 支持自动生成主键 -->
<setting name="useGeneratedKeys" value="false"/>
<!-- 配置默认的执行器 -->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!-- 设置超时时间,单位秒,默认为空 -->
<setting name="defaultStatementTimeout" value="25"/>
<!-- 一次性返回多少数据,默认是 null 返回全部 -->
<setting name="defaultFetchSize" value="100"/>
<!-- 分页设置。mybatis 自带的分页是内存中的假分页,不要用 -->
<setting name="safeRowBoundsEnabled" value="false"/>
<!-- 是否允许在嵌套语句中使用结果处理器。一对多多对多场景,肯定也要映射结果撒 -->
<setting name="safeResultHandlerEnabled" value="true"/>
<!-- 指定动态 SQL 生成使用的默认脚本语言。也就是处理动态sql的类 -->
<setting name="defaultScriptingLanguage" value="org.apache.ibatis.scripting.xmltags.XMLLanguageDriver"/>
<!-- 上面是处理动态 SQL,这个是来处理枚举的 -->
<setting name="defaultEnumTypeHandler" value="org.apache.ibatis.type.EnumTypeHandler"/>
<!-- 不常用的 -->
<setting name="proxyFactory" value="CGLIB | JAVASSIST"/>
<setting name="vfsImpl" value="org.mybatis.example.YourselfVfsImpl"/>
<setting name="useActualParamName" value="true"/>
<setting name="configurationFactory" value="org.mybatis.example.ConfigurationFactory"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
</settings>
有一些单独说明一下
- 缓存配置开关:mybatis 分为 一级缓存、二级缓存、自定义的三级缓存,后面专门讲
- 懒加载配置
- 只配置 lazyLoadingEnabled,所有方法都懒加载(但是有些特殊方法不能懒加载)
- aggressiveLazyLoading 简而言之是有特殊方法不懒加载,lazyLoadTriggerMethods 指明哪些是特殊方法
- 自动映射配置
- autoMappingBehavior:查询结果列和实体属性怎么映射
- NONE 不映射;
- PARTIAL 是集合的字段不映射;
- FULL 集合字段也映射
- autoMappingUnknownColumnBehavior:查询结果列对应不上实体属性怎么处理
- NONE 不做任何反应
- WARNING 日志输出警告(日志是 warning 级别,AutoMappingUnknownColumnBehavior)
- FAILING 抛异常(SqlSessionException)
- mapUnderscoreToCamelCase:查询结果列自动转驼峰
- autoMappingBehavior:查询结果列和实体属性怎么映射
typeAliases
别名配置,两种方式
-
方式一
<typeAliases> <typeAlias alias="Author" type="domain.blog.Author"/> <typeAlias alias="Blog" type="domain.blog.Blog"/> </typeAliases>
-
方式二
配置文件中只写包名,这个包下的 java 类都会以类名作为别名(第一个字幕小写)
<typeAliases> <package name="domain.blog"/> </typeAliases>
如果包下的某个类不想使用默认的别名,还可以单独配置
// 默认是 author,使用注解 @Alias 自定义别名 @Alias("author1") public class Author { ... }
typeHandlers
类型处理器,sql 查询结果字段的 jdbc 类型处理成 java 类型,比如 jdbc 的 datetime、varchar 转为 java 的 Date、String 等
有需要可以自定义类型处理器,继承 BaseTypeHandler 重写里面的方法即可。比如数据脱敏,性别枚举转换等
一般不会全局配置类型处理器,一般都是某些表的个别字段做处理,在 mapper 映射文件中再说
objectFactory
对象工厂的目的是创建结果集对应的对象,一般使用默认的就行了不需要扩展,但是对于某些特殊的场景还是有点用:比如查询学生列表,想给每个学生根据成绩再增加一个排名。其实可以 mybatis 映射完成后,在 java 中遍历结果集,然后再设置排名
plugins
非常重要,后面专门讲插件
environments
用来配置数据环境的,事务、数据源、连接使用池化技术等,可以配置多个,但是必须指定一个作为默认环境
虽然可以使用多个环境,但是每个 SqlSessionFactory 实例只能选择一种环境
配置示例:
<environments default="dev">
<!-- 开发环境 -->
<environment id="dev">
<!-- 事务管理器,可选 JDBC 和 MANAGED,默认是 JDBC -->
<transactionManager type="JDBC">
<!-- 跳过自动提交 -->
<property name="skipSetAutoCommitOnClose" value="true" />
</transactionManager>
<!-- 数据源,不使用数据库连接池,也就不用配置最大连接数等 -->
<dataSource type="UNPOOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
<!-- 测试环境 -->
<environment id="sit">
...
</environment>
<!-- 准生产环境 -->
<environment id="uat">
...
</environment>
<!-- 生产环境 -->
<environment id="prod">
...
</environment>
</environments>
环境总的来说分为两部分:事务管理器 和 数据源,分别来说下
- 事务管理器
- 事务包含 3 个步骤,提交、回滚、关闭连接。为了统一,所有的数据库对应的数据管理器都会有这三个步骤,但是某些数据库不仅不需要,反而变麻烦了,比如 mysql 本身就是启用了自动提交,这里为了统一还是为 启用事务、然后再提交。可以配置
skipSetAutoCommitOnClose = true
来跳过自动提交步骤 - 可选的有 JDBC 和 MANAGED。JDBC:使用 JDBC 的事务管理器,MANAGED:自身不会实现事务管理,使用 web 容器(如 EJB,webLogic)来实现,如果是不是 web 项目,意味着事务会无效。 JDBC 和 MANAGED 其实是个别名,分别对应 JdbcTransaction 和 ManagedTransaction 两个类来实现的
- 如果是 spring 项目,不用配置事务管理器了,因为 Spring 模块会使用自带的管理器来覆盖前面的配置,具体的实现类是 SpringManagedTransaction
- 事务包含 3 个步骤,提交、回滚、关闭连接。为了统一,所有的数据库对应的数据管理器都会有这三个步骤,但是某些数据库不仅不需要,反而变麻烦了,比如 mysql 本身就是启用了自动提交,这里为了统一还是为 启用事务、然后再提交。可以配置
- 数据源
- 包含数据库连接信息、用户名、密码、超时、隔离级别
- 可选的类型有三个:UNPOOLED、POOLED、JNDI 。UNPOOLED:不适用池化技术;POOLED:使用池化技术,意味着配置信息在 UNPOOLED 的基础上还能配置连接池信息,比如 最大连接数、连接空闲存活时间等;JNDI:同事务管理的,也是兼容 EJB 这些容器的,现在的项目都没这些老古董了
databaseIdProvider
数据库厂商标识,卷不动了
mappers
mybatis 的全局配置已经 ok 了,现在就该轮到各个映射文件了 ,首先要知道这些文件在什么地方,多种方式来指定,如下:
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
mapper 映射文件
cache
– 该命名空间的缓存配置。cache-ref
– 引用其它命名空间的缓存配置。resultMap
– 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。parameterMap
– 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。sql
– 可被其它语句引用的可重用语句块。insert
– 映射插入语句。update
– 映射更新语句。delete
– 映射删除语句。select
– 映射查询语句。
这个打交道的次数很多了,namespace,id,select,update 这些已经神熟悉了,捡一些说一下
-
cache、cache-ref:mybatis 分为 一级缓存、二级缓存、自定义的三级缓存,后面专门讲
-
resultMap
- 配合 select 标签使用,处理查询结果的列和实体属性映射关系
- 当查询结果列和实体属性名不对应的时,使用 as 别名
- 一对多、多对多,后面专门讲
-
sql:sql 片段,目的是将重复的 SQL 语句抽取出来,放到
<sql>
标签中,可以进行复用<!-- sql 片段 --> <sql id="where-title-author"> <if test="title!=null"> title like concat('%',#{title},'%') </if> <if test="author!=null"> and author = #{author} </if> </sql> <!-- 使用 --> <select id="queryBlogIf" resultType="blog" parameterType="map"> select * from blog <where> <include refid="where-title-author"></include> </where> </select>
<!-- sql 片段 --> <sql id="querySql"> ID, NAME, AGE </sql> <!-- 使用 --> <select id="queryAll" resultType="student"> select <include refid="querySql" /> from t_student </select>