MyBatis
的全局配置文件(SqlMapConfig.xml
,名字不固定)包含了影响 MyBatis
行为甚深的设置和属性信息。 XML
文档的高层级结构如下:
从前面MyBatis(二)—— 入门程序之单表增删查改和MyBatis(三) ——数据访问对象(DAO)的开发的实战中,其实多多少少都有些印象了。
SqlMapConfig.xml
中除了xml
约束头之外,实际需要配置的内容都包含在
中。这里需要注意,上面列出来的结构里,不是所有内容都需要去做配置的,有需要才去配,没有需要的时候可以缺省。
properties
通过resource
属性(配置文件来自于类路径)或者url
属性(配置文件来自于磁盘路径或网络)加载外部的配置文件(需要特别注意路径问题),一些外部化的、可替代的配置,可以通过properties
的子属性,即property
来传递。例如:
<properties resource="com/mybatis/example/db.properties">
<property name="username" value="example"/>
<property name="password" value="example"/>
properties>
上面定义的username
和passewoed
在整个配置文件中可用,这样就可以在后续的配置中实现动态配置:
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
dataSource>
上面这段配置里,因为前面配置了username
和password
,所以这两个属性将从前面的配置中获取,driver
和 url
将从resource
属性中定义的配置文件中获取。(这里只为演示,一般除特殊情况外,这些属性都从配置文件中获取,为避免造成混乱,最好所有需要配置的东西都放在配置文件内并适当做好备注)。
另外,SqlSessionFactoryBuider
提供了几个可以传递属性的build
方法,也就意味着我们可以在创建会话工厂的时候传入属性。
总结下来就是,properties
是用来引入配置的,这些配置项可以定义在三个地方:配置文件、property
子属性、方法体内。MyBatis
按照如下的顺序加载它们:
properties
元素体内定义的属性(也就是在properties
内的property
)首先被读取;resource
属性或 url
属性中加载的配置文件中的属性第二被读取,它会覆盖已经存在的完全一样的属性;因此,最高优先级的属性是那些作为方法参数的,然后是resource/url
加载的属性,最后是properties
元素中指定的属性。
settings
用于MyBatis
全局参数配置,这些是极其重要的调整,它们会修改 MyBatis
在运行时的行为方式。
里面各个属性的含义和默认值,用户文档已经说得比较清楚了,这儿不赘述了,把表格粘在下边儿。
typeAliases
用于定义别名。从前面文章的例子可以看到,我们需要在配置文件中指定出入参类型,而且还是全路径,总是这样输入全路径会很不方便。
于是,我们可以为这个全路径定义一个别名,在后面的配置中就可以使用这个别名代替相关的全路径配置。配置也很简单,type
属性中放置类的全路径,alias
属性中放置代替这个全路径额别名,如下:
<typeAliases>
<typeAlias alias="Pojo" type="com.mybatis.example.Pojo"/>
typeAliases>
另外,可以批量定义别名,批量定义时在package
属性内填入包名,MyBatis
自动扫描包中的类,生成的别名为类名(首字母大小写均可):
<typeAliases>
<typeAlias package="com.mybatis.example"/>
typeAliases>
对于普通的 Java
类型,有许多内建的类型别名。它们都是大小写不敏感的,由于重载
的名字,要注意原生类型的特殊处理。
无论是 MyBatis
在预处理语句中设置一个参数,还是从结果集中取出一个值时,类型处
理器被用来将获取的值以合适的方式转换成 Java
类型,typeHandler
就充当这样的角色,用于完成jdbc
类型和java
类型的转换。
可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。要
这样做的话,简单实现 TypeHandler
接口( org.mybatis.type
),然后映射新的类型处理器类到Java 类型,还有可选的一个 JDBC
类型。但是一般情况下,MyBatis
提供的类型已经足够使用,不需要做自定义,因此,这里也不多展开了,详细可参考用户指南。
MyBatis
每次创建结果对象的新实例时,会使用一个 ObjectFactory
实例来完成。如果参
数映射存在,在实例化目标类时,默认的 ObjectFactory
不比使用默认构造方法或带参数的构造方法做的工作多。 可以通过重写默认的 ObjectFactory
创建自己的对象工厂。比如:
// ExampleObjectFactory.java
public class ExampleObjectFactory extends DefaultObjectFactory {
public Object create(Class type) {
return super.create(type);
}
public Object create(Class type,List<Class> constructorArgTypes, List<Object> constructorArgs) {
return super.create(type, constructorArgTypes, constructorArgs);
}
public void setProperties(Properties properties) {
super.setProperties(properties);
}
}
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
<property name="someProperty" value="100"/>
objectFactory>
ObjectFactory
接口非常简单。它包含两个用于创建的方法,一个是默认构造方法create
,另外一个是处理带参数的构造方法create(Class type,List
。最终, setProperties
方法可以被用来配置ObjectFactory
。在初始化ObjectFactory
实例后,objectFactory
元素体中定义的属性会被传递给 setProperties
方法。
MyBatis
允许在某一点拦截已映射语句执行的调用,plugins
就是用来拦截方法调用:
这些类中方法的详情可以通过查看每个方法的签名来发现,而且它们的源代码存在于
MyBatis
的发行包中。尝试修改或覆盖一个给定的方法可能会打破 MyBatis
的核心。这是低层次的类和方法,要谨慎使用插件。使用插件是它们提供的非常简单的力量。简单实现拦截器接口,要确定你想拦截的指定签名。
// ExamplePlugin.java
@Intercepts({
@Signature(type= Executor.class,method = "update",
args = {
MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable
{
return invocation.proceed();
}
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties) {
}
}
// MapperConfig.xml
<plugins>
<plugin interceptor="org.mybatis.example.ExamplePlugin">
<property name="someProperty" value="100"/>
plugin>
plugins>
上面的插件将会拦截在 Executor
实例中所有的“ update
”方法调用,它也是负责低层次
映射语句执行的内部对象。
MyBatis
通过environments
标签下的environment
子标签配置环境。可以为整个应用定义不同的环境,例如,为开发和测试定义不同的环境:
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${developmet.jdbc.driver}"/>
<property name="url" value="${developmet.jdbc.url}"/>
<property name="username" value="${developmet.jdbc.username}"/>
<property name="password" value="${developmet.jdbc.password}"/>
dataSource>
environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${test.jdbc.driver}"/>
<property name="url" value="${test.jdbc.url}"/>
<property name="username" value="${test.jdbc.username}"/>
<property name="password" value="${test.jdbc.password}"/>
dataSource>
environment>
针对不同的环境,SqlSessionFactoryBuilder
提供了重载的build
方法使得可以传入环境变量:
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment);
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment,properties);
上面两个方法中environment
参数是String
类型的,只需要将环境的id
传入即可,以其中一个方法为例:
String enviroment="test";
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,enviroment);
需要注意的是:可以配置多种环境,但只能为每个 SqlSessionFactory
实例选择一个。如果需要连接两个数据库,就需要创建两个 SqlSessionFactory
实例,每个数据库
对应一个。而如果是三个数据库,你就需要三个实例,以此类推。也即,每个数据库对应一个 SqlSessionFactory
。
transactionManager
用于指定事务管理器类型。MyBatis
提供了两种:
JDBC
的提交和回滚设置。它依赖于从数据源得 到的连接来管理事务范围。Spring
或JEE
应用服务器的上下文)。默认 情况下它会关闭连接。然而一些容器并不希望这样,因此如果需要从连接中停止它,将closeConnection
属性设置为 false
。例如:<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
transactionManager>
这两种事务管理器都不需要任何属性。需要注意的是,JDBC
和MANAGED
都是别名,如果需要传入自定义的类型,需要自己再定义别名或者传入类的全路径。自定义事务管理器需要实现两个接口:
public interface TransactionFactory {
void setProperties(Properties props);
Transaction newTransaction(Connection conn, boolean autoCommit);
}
public interface Transaction {
Connection getConnection();
void commit() throws SQLException;
void rollback() throws SQLException;
void close() throws SQLException;
}
dataSource
元素使用标准的 JDBC
数据源接口来配置 JDBC
连接对象的资源。
数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。
MyBatis
提供了三种内建的数据源类型:
UNPOOLED
类型的数据源仅仅需要配置以下 5
种属性:
JDBC
驱动的 Java
类全限定名;JDBC URL
地址;作为可选项,你也可以传递属性给数据库驱动。只需在属性名加上“driver.”
前缀即可,例如:driver.encoding=UTF8
。这将通过 DriverManager.getConnection(url, driverProperties)
方法传递值为 UTF8
的 encoding
属性给数据库驱动。
UNPOOLED
下的属性外,还有更多属性用来配置 POOLED
的数据源:
10
checked out
)时间,默认值:20000
毫秒(即 20
秒)20000
毫秒(即 20
秒)。poolMaximumIdleConnections
与poolMaximumLocalBadConnectionTolerance
之和。 默认值:3
(新增于 3.4.5
)“NO PING QUERY SET”
,这会引起许多数据库驱动连接由一个错误信息而导致失败。poolPingQuery
属性为一个可执行的 SQL
语句(最好是一个速度非常快的 SQL
语句),默认值:false
。poolPingQuery
的频率。可以被设置为和数据库连接超时时间一样,来避免不必要的侦测,默认值:0
(即所有连接每一时刻都被侦测 — 当且仅当poolPingEnabled
为 true
时适用)。EJB
或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI
上下文的数据源引用。这种数据源配置只需要两个属性:InitialContext
中寻找上下文(即,initialContext.lookup(initial_context
))。这是个可选属性,如果忽略,那么将会直接从InitialContext
中寻找 data_source
属性。initial_context
配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext
中查找。和其他数据源配置类似,可以通过添加前缀“env.”
直接把属性传递给 InitialContext
。比如:env.encoding=UTF8
这就会在 InitialContext
实例化时往它的构造方法传递值为 UTF8
的 encoding
属性。
可以通过实现接口 org.apache.ibatis.datasource.DataSourceFactory
来使用第三方数据源实现;org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory
可被用作父类来构建新的数据源适配器,比如下面这段插入 C3P0
数据源所必需的代码:
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {
public C3P0DataSourceFactory() {
this.dataSource = new ComboPooledDataSource();
}
}
为了令其工作,记得在配置文件中增加对应的属性。
mappers
用于加载SQL
映射文件,可以使用resource
(类路径)和url
(磁盘路径或者网络)属性进行加载:
<mappers>
<mapper resource="com/***/mapper/UserMapper.xml"/>
<mapper url="file:///var/sqlmap/UserMapper.xml"/>
mappers>
也可以通过Mapper
接口加载:
<mappers>
<mapper class="com.***.mapper.UserMapper"/>
mappers>
需要通过class
属性加载Mapper
接口的全路径名称,同时,需要注意,这种方法使用与使用Mapper
开发DAO
的情况,且 Mapper.java
和Mapper.xml
需要在同一目录下且名字相同(如同样在com/***/mapper
包下的UserMapper.java
和UserMapper.xml
)。
当需要加载多个映射文件时,可以把这些映射文件放到同一个包里面,方便管理,同时也可以使用批量加载的方法一次性加载:
<mappers>
<package name="com.***.mapper"/>
mappers>
name
属性指定Mapper
接口存在的包名,MyBatis
会自动扫描所有的接口进行加载,需要遵守的规律如上一段所描述。
本文介绍了MyBatis
全局配置文件中的一些属性及一些常用的使用方法,其中高亮的部分属于比较常用且重要的内容。当然,里面还有很多内容没有展开,例如settings
里面的其他设置、typeHandler
的开发等,对于这些内容,可查阅MyBatis
的手册查找相关的资料。
【1】MyBatis User Guide
【2】传智 SpringMVC + MyBatis由浅入深 教程