深入MyBatis的配置文件
一、MyBatis 初始化
MyBatis 初始化基本过程:
SqlSessionFactoryBuilder 根据传入的数据流生成 Configuration 对象,然后根据 Configuration 对象创建默认的 SqlSessionFactory 实例。
MyBatis初始化详细过程:
- 调用 SqlSessionFactoryBuilder 对象的 builder(inputStream) 方法。
- SqlSessionFactoryBuilder 会根据输入流 inputStream 等信息创建 XMLConfigBuilder 对象
- SqlSessionFactoryBuilder 调用 XMLConfigBuilder 对象的 parse() 方法
- XMLConfigBuilder 对象解析XML配置文件返回 Configuration 对象
- SqlSessionFactoryBuilder 根据 Configuration 对象创建一个 DefaultSessionFactory 对象
- SqlSessionFactoryBuilder 返回 DefaultSessionFactory 对象给客户端,供客户端使用
二、MyBatis 的配置文件结构
顶层configuration 配置
1. properties 属性
properties 属性可以给系统配置一些运行参数,可以放在 XML 文件或者 properties 文件中,而不是放在 Java 编码中,这样的好处在于方便参数修改,而不会引起代码的重新编译。
-
property 子元素
可以使用 property 子元素将数据库连接的相关配置进行改写,如下所示。
<?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> <!-- MySQL数据库驱动 --> <property name="database.driver" value="com.mysql.jdbc.Driver"/> <!-- 连接数据库的URL --> <property name="database.url" value="jdbc:mysql://localhost/mybatis?characterEncoding=utf8"/> <!-- 连接数据库的用户名 --> <property name="database.username" value="root"/> <!-- 连接数据库的密码 --> <property name="database.password" value="123456"/> </properties> <typeAliases> <typeAlias type="com.zhang.pojo.Student" alias="Student"/> </typeAliases> <!-- 配置mybatis运行环境 --> <environments default="development"> <environment id="development"> <!-- 使用JDBC的事务管理 --> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <!-- MySQL数据库驱动 --> <property name="driver" value="${database.driver}"/> <!-- 连接数据库的URL --> <property name="url" value="${database.url}"/> <!-- 连接数据库的用户名 --> <property name="username" value="${database.username}"/> <!-- 连接数据库的密码 --> <property name="password" value="${database.password}"/> </dataSource> </environment> </environments> <!-- 将mapper文件加入到配置文件中 --> <mappers> <mapper resource="com/zhang/mapper/StudentMapper.xml"/> </mappers> </configuration>
这里使用了元素 下的子元素 定义,用字符串 database.username 定义数据库用户名,然后就可以在数据库定义中引入这个已经定义好的属性参数,如 ${database.username},这样定义一次就可以到处引用了。但是如果属性参数有成百上千个,显然使用这样的方式不是一个很好的选择,这个时候可以使用 properties 文件。
-
使用 properties 文件
使用 properties 文件是比较普遍的方法,一方面这个文件十分简单,其逻辑就是键值对应,我们可以配置多个键值放在一个 properties 文件中,也可以把多个键值放到多个 properties 文件中,这些都是允许的,它方便日后维护和修改。
我们创建一个文件 db.properties 放到 classpath 的路径下,如下所示。
database.driver=com.mysql.jdbc.Driver database.url=jdbc:mysql://localhost/mybatis?characterEncoding=utf8 database.username=root database.password=123456
在 MyBatis 中通过 的属性 resource 来引入 properties 文件。
<properties resource="jdbc.properties"/>
也可以按 ${database.username} 的方法引入 properties 文件的属性参数到 MyBatis 配置文件中。这个时候通过维护 properties 文件就可以维护我们的配置内容了。
2. settings 设置
在 MyBatis 中 settings 是最复杂的配置,它能深刻影响 MyBatis 底层的运行,但是在大部分情况下使用默认值便可以运行,所以在大部分情况下不需要大量配置它,只需要修改一些常用的规则即可,比如自动映射、驼峰命名映射、级联规则、是否启动缓存、执行器(Executor)类型等。settings 配置项说明,如表 1 所示。
配置项 | 作用 | 配置选项 | 默认值 |
---|---|---|---|
cacheEnabled | 该配置影响所有映射器中配置缓存的全局开关 | true / false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。在特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态 | true / false | false |
aggressiveLazyLoading | 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载 | true / felse | 版本3.4.1之前 true,之后 false |
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。NONE 表示取消自动映射。PARTIAL 表示只会自动映射,没有定义嵌套结果集和映射结果集。FULL 会自动映射任意复杂的结果集(无论是否嵌套) | NONE / PARTIAL / FULL | PARTIAL |
mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射 | true / false | false |
defaultExecutorType | 配置默认的执行器。SIMPLE 是普通的执行器;REUSE 会重用预处理语句(prepared statements);BATCH 执行器将重用语句并执行批量更新 | SIMPLE / REUSE / BATCH | SIMPLE |
settings 的配置项很多,但是真正用到的不会太多,我们把常用的配置项研究清楚就可以了,比如关于缓存的 cacheEnabled,关于级联的 lazyLoadingEnabled 和 aggressiveLazy Loading,关于自动映射的 autoMappingBehavior 和 mapUnderscoreToCamelCase,关于执行器类型的 defaultExecutorType 等。
这里给出一个全量的配置样例,如下所示。
<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>
3. typeAliases 类型命名
类型别名是为Java类型设置一个短的名字。它只和XML配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
<typeAliases><!--别名-->
<typeAlias alias="user" type="com.zhang.pojo.User"/>
<typeAlias alias="role" type="com.zhang.pojo.Role"/>
</typeAliases>
这样配置,user可以在任何使用 com.zhang.pojo.User 的地方使用。
这样就可以定义一个别名了。如果有很多类需要定义别名,那么用这样的方式进行配置可就不那么轻松了。MyBatis 还支持扫描别名。比如上面的两个类都在包 com.zhang.pojo 之下,那么就可以定义为:
<typeAliases><!--别名-->
<package name="com.zhang.pojo"/>
</typeAliases>
这样 MyBatis 将扫描这个包里面的类,将其第一个字母变为小写作为其别名,比如类 Role 的别名会变为 role,而 User 的别名会变为 user。使用这样的规则,有时候会出现重名。这个时候可以使用 MyBatis 提供的注解 @Alias(“user3”)进行区分,如下所示。
package com.zhang.pojo;
@Alias("user1")
public Class User{
......
}
4. environments 配置环境
MyBatis 的配置环境实际就是数据源的配置。MyBatis 可以配置多个环境,这种机制使得MyBatis 可以将 SQL 映射应用于多种数据库中。尽管可以配置多个环境,但是每个 SqlSessionFactory 实例只能选择一个环境即每个数据库对应一个 SqlSessionFactory 实例。
环境实例配置如下:
<!-- 配置mybatis运行环境 -->
<environments default="development">
<environment id="development">
<!-- 使用JDBC的事务管理 -->
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<!-- MySQL数据库驱动 -->
<property name="driver" value="${database.driver}"/>
<!-- 连接数据库的URL -->
<property name="url" value="${database.url}"/>
<!-- 连接数据库的用户名 -->
<property name="username" value="${database.username}"/>
<!-- 连接数据库的密码 -->
<property name="password" value="${database.password}"/>
</dataSource>
</environment>
</environments>
- 默认的环境ID(default="development")
- 每个 environment 元素定义的环境ID (id=“development”)
- 事务管理器的配置 (< transactionManager type=“JDBC”></ transactionManager>)
- 数据源的配置(< dataSource type=“POOLED”></ dataSource>)
4.1 环境ID
环境ID可以随意命名,建议简介有意义,而默认环境一定要匹配定义的其中一个环境ID
4.2 transactionManager(事务管理器)
MyBatis 为 Transaction 提供了两个实现类:JdbcTransaction 和 ManagedTransaction
于是它对应着两种工厂:JdbcTransactionFactory 和 ManagedTransactionFactory,这个工厂需要实现 TransactionFactory 接口,通过它们会生成对应的 Transaction 对象。于是可以把事务管理器配置成为以下两种方式:
<transactionManager type="JDBC"/>
<transactionManager type="MANAGED"/>
- JDBC
这个配置就是直接使用了JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事务范围。 - MANAGED
它的提交和回滚方法不用任何操作,而是把事务交给容器处理。在默认情况下,它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。
transactionManager 的 MANAGED 配置实例如下:<transactionManager type="MANAGED"> <property name="closeConnection" value="false"> </transactionManger>
4.3 environment 数据源环境
environment 的主要作用是配置数据库,在 MyBatis 中,数据库通过 PooledDataSource Factory、UnpooledDataSourceFactory 和 JndiDataSourceFactory 三个工厂类来提供,前两者对应产生 PooledDataSource、UnpooledDataSource 类对象,而 JndiDataSourceFactory 则会根据 JNDI 的信息拿到外部容器实现的数据库连接对象。
在MyBatis 中有 UNPOOLED、POOLED 和 JNDI 三种数据源类型:
-
UNPOOLED
UNPOOLED 采用非数据库池的管理方式,每次请求都会打开一个新的数据库连接,所以创建会比较慢。在一些对性能没有很高要求的场合可以使用它。
UNPOOLED 类型的数据源可以配置以下几种属性:- driver:数据库驱动名,比如Mysql的 com.mysql.jdbc.driver
- url:连接数据库的URL 比如 mysql:jdbc://localhost/mybatis
- username:登录数据库的用户名
- password:登陆数据库的密码
- defaultTransactionIsolationLevel:默认的连接事务隔离级别
-
POOLED
数据源 POOLED 利用“池”的概念将 JDBC 的 Connection 对象组织起来,它开始会有一些空置,并且已经连接好的数据库连接,所以请求时,无须再建立和验证,省去了创建新的连接实例时所必需的初始化和认证时间。它还控制最大连接数,避免过多的连接导致系统瓶颈。除了上述提到的 UNPOOLED 的 5 种属性外,还可以使用更多属性来配置 POOLED 的数据源:- poolMaximumActiveConnections:在任意时间都存在的活动(也就是正在使用)连接数量,默认值为 10
- poolMaximumldleConnections:任意时间可能存在的空闲连接数
- poolMaximumCheckoutTime:在被强制返回之前,池中连接被检出(checked out)的时间,默认值为 20 000 毫秒(即 20 秒)
- poolTimeToWait: 是一个底层设置,如果获取连接花费相当长的时间,它会给连接池打印状态日志,并重新尝试获取一个连接(避免在误配置的情况下一直失败),默认值为 20 000 毫秒(即 20 秒)。
- poolPingQuery: 为发送到数据库的侦测查询,用来检验连接是否处在正常工作秩序中,并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动失败时带有一个恰当的错误消息。
- poolPingEnabled:为是否启用侦测查询。若开启,也必须使用一个可执行的 SQL 语句设置 poolPingQuery 属性(最好是一个非常快的 SQL),默认值为 false。
- poolPingConnectionsNotUsedFor:为配置 poolPingQuery 的使用频度。这可以被设置成匹配具体的数据库连接超时时间,来避免不必要的侦测,默认值为 0(即所有连接每一时刻都被侦测——仅当 poolPingEnabled 为 true 时适用)。
-
JNDI
数据源 JNDI 的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。这种数据源配置只需要两个属性:- initial_context:用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。initial_context 是个可选属性,如果忽略,那么 data_source 属性将会直接从 InitialContext 中寻找。
- data_source:是引用数据源实例位置上下文的路径。当提供 initial_context 配置时,data_source 会在其返回的上下文中进行查找;当没有提供 initial_context 时,data_source 直接在 InitialContext 中查找。
dataSource 的 JDNI 配置示例如下:
<dataSource type="JDNI"> <property name="initial_context" value="java:/comp/env"/> <property name="data_source" value="fkjavads"/> </dataSource>
参考文章:
- 《Spring + MyBatis 企业应用开发》
- 《C语言中文网》