本文参考如下:
- 配置文档 http://www.mybatis.org/mybatis-3/zh/configuration.html
- 代码 XMLConfigBuilder
处理流程
构造 XMLConfigBuilder 对象 parse
创建 Configuration 对象 config
创建 XPathParser 对象 parser
调用 XMLConfigBuilder 的 parse 方法
调用 parser 的 evalNode 方法
依次读取 properties,settings,typeAliases, plugins, objectFactory
配置
properties
读取顺序(后面覆盖前面):
- 在 properties 元素内的指定的属性首先被读取。
- 然后根据 properties 元素中的 resource 属性读取类路径下属性文件或根据 url 属性指定的路径读取属性文件。
- 方法参数传递的属性。
该属性下设置的 key-value 可以用于其他地方。
settings
settings 下的属性必须是在 Configuration 下定义的属性,否则抛出异常。
问题:vfsImpl : 有什么用?
默认值配置
<settings>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="NONE"/>
<setting name="aggressiveLazyLoading" value="false"/>
<setting name="cacheEnabled" value="true"/>
<setting name="callSettersOnNulls" value="false"/>
<setting name="configurationFactory" value=""/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value=""/>
<setting name="defaultFetchSize" value=""/>
<setting name="defaultScriptingLanguage" value=""/>
<setting name="defaultEnumTypeHandler" value=""/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadingEnabled" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="logPrefix" value=""/> //没有默认值
<setting name="logImpl" value=""/> //没有默认值
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="proxyFactory" value=""/>
<setting name="returnInstanceForEmptyRow" value="false"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="safeResultHandlerEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="useActualParamName" value="true"/>
</settings>
typeAliases
功能
- 增加类名和类的映射关系
- 示例 1 加入 Configuration 的 typeAliasRegistry;示例 2 加入 BaseBuilder 的 typeAliasRegistry
除了默认关系, 还可以在 typaAliases 配置下注册,如示例 1 和示例 2
typeAliases 支持示例1 和 示例 2 两种配置类型别名的方式,但是只能支持其中一种。如果示例1 的配置存在,示例 2 的配置会被忽略。否则示例 2 的配置生效。
示例 1
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
包 domain.blog 下的类,如果有 Alias 注解,否则会用类的 SampleName 的形式为类型
@Alias("author")
public class Author {
...
}
示例 2
<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>
plugins
功能
- 实例化 interceptor 对应的类 class
- 将 plugin 中的所有 property 设置为 class 的属性
- 将 class 作为拦截器加入 Configuration
示例 1
<plugins>
<plugin interceptor="org.mybatis.example.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
创建 org.mybatis.example.ExamplePlugin 对象,并设置下面 property 中的属性
objectFactory
功能
- 实例化 type 对应的类 class
- 将 objectFactory 中的所有 property 设置为 class 的属性
- 将 class 作为 Configuration 的 objectFactory
示例 1
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
<property name="someProperty" value="100"/>
</objectFactory>
objectWrapperFactory
功能
- 实例化 type 对应的类 class
- 将 class 作为 Configuration 的 objectWrapperFactory
<objectWrapperFactory type="org.mybatis.example.ExampleObjectFactory">
</objectWrapperFactory>
reflectorFactory
功能
- 实例化 type 对应的类 class
- 将 class 作为 Configuration 的 reflectorFactory
<reflectorFactory type="org.mybatis.example.ExampleObjectFactory">
</reflectorFactory>
environments
功能
- 解析 default 对应的 environment
- 设置 Configuration 的 environment
示例
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"> <!-- MANAGED -->
<property name="..." value="..."/>
</transactionManager>
<dataSource type="POOLED"> <!-- UNPOOLED|POOLED|JNDI -->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
- default 必须与某个 environment 的 id 匹配
- 设置 JDBC 对应的对象属性为 transactionManager 下的 property
- 设置 POOLED 对应的对象属性为 dataSource 下的 property
这个数据源的实现只是每次被请求时打开和关闭连接。虽然有点慢,但对于在数据库连接可用性方面没有太高要求的简单应用程序来说,是一个很好的选择。 不同的数据库在性能方面的表现也是不一样的,对于某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。UNPOOLED 类型的数据源仅仅需要配置以下 5 种属性:
driver
– 这是 JDBC 驱动的 Java 类的完全限定名(并不是 JDBC 驱动中可能包含的数据源类)。url
– 这是数据库的 JDBC URL 地址。username
– 登录数据库的用户名。password
– 登录数据库的密码。defaultTransactionIsolationLevel
– 默认的连接事务隔离级别。
作为可选项,你也可以传递属性给数据库驱动。要这样做,属性的前缀为“driver.”,例如:
driver.encoding=UTF8
这将通过 DriverManager.getConnection(url,driverProperties) 方法传递值为 UTF8
的 encoding
属性给数据库驱动。
POOLED
这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这是一种使得并发 Web 应用快速响应请求的流行处理方式。
除了上述提到 UNPOOLED 下的属性外,还有更多属性用来配置 POOLED 的数据源:
poolMaximumActiveConnections
– 在任意时间可以存在的活动(也就是正在使用)连接数量,默认值:10poolMaximumIdleConnections
– 任意时间可能存在的空闲连接数。poolMaximumCheckoutTime
– 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)poolTimeToWait
– 这是一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直安静的失败),默认值:20000 毫秒(即 20 秒)。poolMaximumLocalBadConnectionTolerance
– 这是一个关于坏连接容忍度的底层设置, 作用于每一个尝试从缓存池获取连接的线程. 如果这个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过poolMaximumIdleConnections
与poolMaximumLocalBadConnectionTolerance
之和。 默认值:3 (新增于 3.4.5)poolPingQuery
– 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动失败时带有一个恰当的错误消息。poolPingEnabled
– 是否启用侦测查询。若开启,需要设置poolPingQuery
属性为一个可执行的 SQL 语句(最好是一个速度非常快的 SQL 语句),默认值:false。poolPingConnectionsNotUsedFor
– 配置 poolPingQuery 的频率。可以被设置为和数据库连接超时时间一样,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。
databaseIdProvider
功能
- 解析 type 创建 databaseIdProvider
- 从 environment 获取 DataSource,设置 Configuration 的 databaseId
示例
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver"/>
<property name="DB2" value="db2"/>
<property name="Oracle" value="oracle" />
</databaseIdProvider>
typeHandler
- 如果是 package,会将 package 下的类注册,否则将 jdbcType,javaType,handler 注册到Configuration 的 typeHandlerRegistry
示例 1
<typeHandlers>
<package name="org.mybatis.example"/>
</typeHandlers>
示例 2
<typeHandlers>
<typeHandler handler="org.mybatis.example.ExampleTypeHandler" jdbcType="", javaType=""/>
</typeHandlers>
注: MyBatis 不会窥探数据库元信息来决定使用哪种类型,所以你必须在参数和结果映射中指明那是 VARCHAR 类型的字段, 以使其能够绑定到正确的类型处理器上。 这是因为:MyBatis 直到语句被执行才清楚数据类型。
通过类型处理器的泛型,MyBatis 可以得知该类型处理器处理的 Java 类型,不过这种行为可以通过两种方法改变:
- 在类型处理器的配置元素(typeHandler element)上增加一个
javaType
属性(比如:javaType="String"
); - 在类型处理器的类上(TypeHandler class)增加一个
@MappedTypes
注解来指定与其关联的 Java 类型列表。 如果在javaType
属性中也同时指定,则注解方式将被忽略。
可以通过两种方式来指定被关联的 JDBC 类型:
- 在类型处理器的配置元素上增加一个
jdbcType
属性(比如:jdbcType="VARCHAR"
); - 在类型处理器的类上(TypeHandler class)增加一个
@MappedJdbcTypes
注解来指定与其关联的 JDBC 类型列表。 如果在jdbcType
属性中也同时指定,则注解方式将被忽略。
当决定在ResultMap
中使用某一TypeHandler时,此时java类型是已知的(从结果类型中获得),但是JDBC类型是未知的。 因此Mybatis使用javaType=[TheJavaType], jdbcType=null
的组合来选择一个TypeHandler。 这意味着使用@MappedJdbcTypes
注解可以限制TypeHandler的范围,同时除非显式的设置,否则TypeHandler在ResultMap
中将是无效的。 如果希望在ResultMap
中使用TypeHandler,那么设置@MappedJdbcTypes
注解的includeNullJdbcType=true
即可。 然而从Mybatis 3.4.0开始,如果只有一个注册的TypeHandler来处理Java类型,那么它将是ResultMap
使用Java类型时的默认值(即使没有includeNullJdbcType=true
)。
mapper
功能
- 如果是 package,扫描 name 对应的包,否则构造 XMLMapperBuilder 对象,调用 parser 方法
示例
<!-- 使用相对于类路径的资源引用 -->
<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>
- resourde, url, class 同时只能有一个生效,优先级 resource > url > class
附录
mybatis 默认数据库类型与 Java 映射关系
string: String
byte: Byte
long: Long
short: Short
int: Integer
integer: Integer
double: Double
float: Float
boolean: Boolean
byte[]: Byte[]
long[]: Long[]
short[]: Short[]
int[]: Integer[]
integer[]: Integer[]
double[]: Double[]
float[]: Float[]
boolean[]: Boolean[]
_byte: byte
_long: long
_short: short
_int: int
_integer: int
_double: double
_float: float
_boolean: boolean
_byte[]: byte[]
_long[]: long[]
_short[]: short[]
_int[]: int[]
_integer[]: int[]
_double[]: double[]
_float[]: float[]
_boolean[]: boolean[]
date: Date
decimal: BigDecimal
bigdecimal: BigDecimal
biginteger: BigInteger
object: Object
date[]: Date[]
decimal[]: BigDecimal[]
bigdecimal[]: BigDecimal[]
biginteger[]: BigInteger[]
object[]: Object[]
map: Map
hashmap: HashMap
list: List
arraylist: ArrayList
collection: Collection
iterator: Iterator
ResultSet: ResultSet