[02] mybatis-config.xml 全局配置文件解析
本篇会摘录mybatis全局配置文件中比较常见常用的一些配置进行说明,其实官方文档已经写得足够清晰了(关键是还有中文版完全不慌),此处记录重要还是作为个人的巩固记录。
1、properties
在全局配置文件中,属性的值是可以由外部配置进行动态替换的,这也就使我们把诸如 “数据库连接信息放到单独的文件” 成为可能,这里有两种方式:
- 配置信息放在常见的 .properties 文件中,通过 resource 属性来引入
- 直接通过 property 属性进行定义
如下有 .properties 文件:
jdbc.username=root
jdbc.password=dev
2
1
jdbc.username=root
2
jdbc.password=dev
则我们在配置文件中配置数据库连接信息可以这样:
<configuration>
<properties resource="db.properties">
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/dbgirl" />
</properties>
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<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}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="sqlmapper/GirlMapper.xml"/>
</mappers>
</configuration>
23
1
<configuration>
2
<properties resource="db.properties">
3
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
4
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/dbgirl" />
5
</properties>
6
7
<environments default="development">
8
<environment id="development">
9
<!-- 使用jdbc事务管理 -->
10
<transactionManager type="JDBC"/>
11
<!-- 数据库连接池 -->
12
<dataSource type="POOLED">
13
<property name="driver" value="${jdbc.driver}"/>
14
<property name="url" value="${jdbc.url}"/>
15
<property name="username" value="${jdbc.username}"/>
16
<property name="password" value="${jdbc.password}"/>
17
</dataSource>
18
</environment>
19
</environments>
20
<mappers>
21
<mapper resource="sqlmapper/GirlMapper.xml"/>
22
</mappers>
23
</configuration>
属性值通过表达式 ${ } 来读取,如上例中 driver 和 url 将从 properties 的元素 <property> 中读取,而 username 和 url 则可以从 db.properties 中读取。当然,更多情况下我们还是统一写在 .properties 中。需要注意的是,properties 元素体内的属性会优先读取,这意味着如果你在两个地方分别定义了同名的属性,那么最终读取到的值会以 .properties 文件中的为准。
2、environments
2.1 environment
如上例中我们的数据库连接配置是放置在 <environments> 中的 <environment> 标签中,这是MyBatis提供的多环境适应机制,例如开发、测试、生产环境都需要有不同的配置,这意味着假如你有生产环境和开发环境两种配置,你可以这样写:
<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="root"/>
<property name="password" value="dev"/>
</dataSource>
</environment>
<!--生产环境-->
<environment id="produce">
<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}"/>
</dataSource>
</environment>
</environments>
24
1
<environments default="development">
2
<!--开发环境-->
3
<environment id="development">
4
<transactionManager type="JDBC"/>
5
<dataSource type="POOLED">
6
<property name="driver" value="${jdbc.driver}"/>
7
<property name="url" value="${jdbc.url}"/>
8
<property name="username" value="root"/>
9
<property name="password" value="dev"/>
10
</dataSource>
11
</environment>
12
13
<!--生产环境-->
14
<environment id="produce">
15
<transactionManager type="JDBC"/>
16
<dataSource type="POOLED">
17
<property name="driver" value="${jdbc.driver}"/>
18
<property name="url" value="${jdbc.url}"/>
19
<property name="username" value="${jdbc.username}"/>
20
<property name="password" value="${jdbc.password}"/>
21
</dataSource>
22
</environment>
23
24
</environments>
- environment 的 id 属性用来区分和定义不同的配置环境
- environments 的 default 用来确定默认使用的配置环境,值是某个 environment 的 id
需要注意的是,尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择其一,如果想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。
为了确定创建哪种环境,我们往往需要将其作为参数传给 SqlSessionFactoryBuilder :
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
2
1
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
2
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
如果忽略将 environment 作为参数传入,则会加载默认的环境:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);
2
1
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
2
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);
2.2 transactionManager
在 MyBatis 中有两种类型的事务管理器:
- JDBC - 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域
- MANAGED - 这个配置从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期
注:如果你在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置
2.3 dataSource
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源,有三种内建的数据源类型
- UNPOOLED - 只是每次被请求时打开和关闭连接
- POOLED - 利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间
- JNDI - 为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用
3、mappers
mappers是用来让告诉MyBatis去哪找到那些执行的SQL语句,可以使用相对于类路径的资源引用, 或完全限定资源定位符(包括 file:/// 的 URL),或类名和包名等:
<!-- 使用相对于类路径的资源引用 -->
<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>
25
1
<!-- 使用相对于类路径的资源引用 -->
2
<mappers>
3
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
4
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
5
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
6
</mappers>
7
8
<!-- 使用完全限定资源定位符(URL) -->
9
<mappers>
10
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
11
<mapper url="file:///var/mappers/BlogMapper.xml"/>
12
<mapper url="file:///var/mappers/PostMapper.xml"/>
13
</mappers>
14
15
<!-- 使用映射器接口实现类的完全限定类名 -->
16
<mappers>
17
<mapper class="org.mybatis.builder.AuthorMapper"/>
18
<mapper class="org.mybatis.builder.BlogMapper"/>
19
<mapper class="org.mybatis.builder.PostMapper"/>
20
</mappers>
21
22
<!-- 将包内的映射器接口实现全部注册为映射器 -->
23
<mappers>
24
<package name="org.mybatis.builder"/>
25
</mappers>
4、settings
在标题1-3中是MyBatis最最基本需要我们改变的配置信息,而settings则是用来改变MyBatis运行时行为的重要调整设置,因为属性较多此处不再细细展开,详见官方文档,如下例为官方提供的部分示例,以在此处做简要说明:
<settings>
<!--全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存-->
<setting name="cacheEnabled" value="true"/>
<!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--是否允许单一语句返回多结果集(需要兼容驱动)-->
<setting name="multipleResultSetsEnabled" value="true"/>
<!--使用列标签代替列名,不同的驱动在这方面会有不同的表现-->
<setting name="useColumnLabel" value="true"/>
<!--允许 JDBC 支持自动生成主键,需要驱动兼容-->
<setting name="useGeneratedKeys" value="false"/>
<!--指定 MyBatis 应如何自动映射列到字段或属性-->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<!--指定发现自动映射目标未知列(或者未知属性类型)的行为-->
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<!--配置默认的执行器-->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!--设置超时时间,它决定驱动等待数据库响应的秒数-->
<setting name="defaultStatementTimeout" value="25"/>
<!--为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖-->
<setting name="defaultFetchSize" value="100"/>
<!--允许在嵌套语句中使用分页,如果允许使用则设置为false-->
<setting name="safeRowBoundsEnabled" value="false"/>
<!--是否开启自动驼峰命名规则映射,即从经典数据库列名A_COLUMN到经典Java属性名aColumn的类似映射-->
<setting name="mapUnderscoreToCamelCase" value="false"/>
<!--利用本地缓存机制防止循环引用和加速重复嵌套查询-->
<setting name="localCacheScope" value="SESSION"/>
<!--当没有为参数提供特定的JDBC类型时,为空值指定哪种JDBC类型-->
<setting name="jdbcTypeForNull" value="OTHER"/>
<!--指定哪个对象的方法触发一次延迟加载,用逗号分隔的方法列表-->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
32
1
<settings>
2
<!--全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存-->
3
<setting name="cacheEnabled" value="true"/>
4
<!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态-->
5
<setting name="lazyLoadingEnabled" value="true"/>
6
<!--是否允许单一语句返回多结果集(需要兼容驱动)-->
7
<setting name="multipleResultSetsEnabled" value="true"/>
8
<!--使用列标签代替列名,不同的驱动在这方面会有不同的表现-->
9
<setting name="useColumnLabel" value="true"/>
10
<!--允许 JDBC 支持自动生成主键,需要驱动兼容-->
11
<setting name="useGeneratedKeys" value="false"/>
12
<!--指定 MyBatis 应如何自动映射列到字段或属性-->
13
<setting name="autoMappingBehavior" value="PARTIAL"/>
14
<!--指定发现自动映射目标未知列(或者未知属性类型)的行为-->
15
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
16
<!--配置默认的执行器-->
17
<setting name="defaultExecutorType" value="SIMPLE"/>
18
<!--设置超时时间,它决定驱动等待数据库响应的秒数-->
19
<setting name="defaultStatementTimeout" value="25"/>
20
<!--为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖-->
21
<setting name="defaultFetchSize" value="100"/>
22
<!--允许在嵌套语句中使用分页,如果允许使用则设置为false-->
23
<setting name="safeRowBoundsEnabled" value="false"/>
24
<!--是否开启自动驼峰命名规则映射,即从经典数据库列名A_COLUMN到经典Java属性名aColumn的类似映射-->
25
<setting name="mapUnderscoreToCamelCase" value="false"/>
26
<!--利用本地缓存机制防止循环引用和加速重复嵌套查询-->
27
<setting name="localCacheScope" value="SESSION"/>
28
<!--当没有为参数提供特定的JDBC类型时,为空值指定哪种JDBC类型-->
29
<setting name="jdbcTypeForNull" value="OTHER"/>
30
<!--指定哪个对象的方法触发一次延迟加载,用逗号分隔的方法列表-->
31
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
32
</settings>
5、typeAliases
类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余,如下配置时 “Blog可以用在任何使用domain.blog.Blog的地方”:
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
8
1
<typeAliases>
2
<typeAlias alias="Author" type="domain.blog.Author"/>
3
<typeAlias alias="Blog" type="domain.blog.Blog"/>
4
<typeAlias alias="Comment" type="domain.blog.Comment"/>
5
<typeAlias alias="Post" type="domain.blog.Post"/>
6
<typeAlias alias="Section" type="domain.blog.Section"/>
7
<typeAlias alias="Tag" type="domain.blog.Tag"/>
8
</typeAliases>
也可以指定一个包名,MyBatis会自动扫描包中的类,自动定义别名(别名即类名,且首字母大小写均可):
<typeAliases>
<package name="domain.blog"/>
<package name="domain.article"/>
<!-- ... -->
</typeAliases>
5
1
<typeAliases>
2
<package name="domain.blog"/>
3
<package name="domain.article"/>
4
<!-- ... -->
5
</typeAliases>
这个配置往往使得我们在mapper.xml中指定输入参数和输出结果类型变得简单方便。
MyBatis中也提供了一些默认支持的别名(默认别名的规则是基本数据类型是名称前加下划线,引用数据类型是首字母小写):
别名 | 映射的类型 | 别名 | 映射的类型 | |
_byte | byte | double | Double | |
_long | long | float | Float | |
_short | short | boolean | Boolean | |
_int | int | date | Date | |
_integer | int | decimal | BigDecimal | |
_double | double | bigdecimal | BigDecimal | |
_float | float | object | Object | |
_boolean | boolean | map | Map | |
string | String | hashmap | HashMap | |
byte | Byte | list | List | |
long | Long | arraylist | ArrayList | |
short | Short | collection | Collection | |
int | Integer | iterator | Iterator | |
integer | Integer |
6、typeHandlers
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成 Java 类型,MyBatis 中已有一些默认的类型处理器,此处列举一二仅供参考,详情参考官方文档:
类型处理器 | Java类型 | JDBC类型 |
StringTypeHandler | java.lang.String | CHAR, VARCHAR |
DateTypeHandler | java.util.Date | TIMESTAMP |
IntegerTypeHandler | java.lang.Integer, int | 数据库兼容的 NUMERIC 或 INTEGER |
FloatTypeHandler | java.lang.Float, float | 数据库兼容的 NUMERIC 或 FLOAT |
... | ... | ... |
当然,你也可以选择重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型,具体实现 org.apache.ibatis.type.TypeHandler 接口,或继承 org.apache.ibatis.type.BaseTypeHandler ,通常来说MyBatis提供的类型处理器已经足够满足日常的开发需要,不需要我们额外自定义。
<!-- mybatis-config.xml -->
<typeHandlers>
<typeHandler handler="org.mybatis.example.CustomTypeHandler"/>
</typeHandlers>
4
1
<!-- mybatis-config.xml -->
2
<typeHandlers>
3
<typeHandler handler="org.mybatis.example.CustomTypeHandler"/>
4
</typeHandlers>
注意:举例来说,假如你自定义的类型处理器是用来处理Java的String和JDBC的VARCHAR类型转换,则自定义处理器会覆盖掉原来默认的处理器。