MyBatis(四) —— MyBatis全局配置文件SqlMapConfig.xml中各属性详解

MyBatis 的全局配置文件(SqlMapConfig.xml,名字不固定)包含了影响 MyBatis 行为甚深的设置和属性信息。 XML文档的高层级结构如下:

  • configuration 配置
    • properties 属性
    • settings 设置
    • typeAliases 类型命名
    • typeHandlers 类型处理器
    • objectFactory 对象工厂
    • plugins 插件
    • environments 环境
      • environment 环境变量
      • transactionManager 事务管理器
      • dataSource 数据源
  • 映射器

从前面MyBatis(二)—— 入门程序之单表增删查改和MyBatis(三) ——数据访问对象(DAO)的开发的实战中,其实多多少少都有些印象了。

SqlMapConfig.xml中除了xml约束头之外,实际需要配置的内容都包含在中。这里需要注意,上面列出来的结构里,不是所有内容都需要去做配置的,有需要才去配,没有需要的时候可以缺省

1. properties 属性

properties通过resource属性(配置文件来自于类路径)或者url属性(配置文件来自于磁盘路径或网络)加载外部的配置文件(需要特别注意路径问题),一些外部化的、可替代的配置,可以通过properties的子属性,即property来传递。例如:

<properties resource="com/mybatis/example/db.properties">
	<property name="username" value="example"/>
	<property name="password" value="example"/>
properties>

上面定义的usernamepassewoed在整个配置文件中可用,这样就可以在后续的配置中实现动态配置:

<dataSource type="POOLED">
	<property name="driver" value="${driver}"/>
	<property name="url" value="${url}"/>
	<property name="username" value="${username}"/>
	<property name="password" value="${password}"/>
dataSource>

上面这段配置里,因为前面配置了usernamepassword,所以这两个属性将从前面的配置中获取,driverurl 将从resource属性中定义的配置文件中获取。(这里只为演示,一般除特殊情况外,这些属性都从配置文件中获取,为避免造成混乱,最好所有需要配置的东西都放在配置文件内并适当做好备注)。

另外,SqlSessionFactoryBuider提供了几个可以传递属性的build方法,也就意味着我们可以在创建会话工厂的时候传入属性。
MyBatis(四) —— MyBatis全局配置文件SqlMapConfig.xml中各属性详解_第1张图片
总结下来就是,properties是用来引入配置的,这些配置项可以定义在三个地方:配置文件、property子属性、方法体内。MyBatis 按照如下的顺序加载它们:

  • properties 元素体内定义的属性(也就是在properties 内的property)首先被读取;
  • resource属性或 url 属性中加载的配置文件中的属性第二被读取,它会覆盖已经存在的完全一样的属性;
  • 作为方法参数传递的属性最后被读取,它也会覆盖任一已经存在的完全一样的属性。

因此,最高优先级的属性是那些作为方法参数的,然后是resource/url 加载的属性,最后是properties元素中指定的属性

2. settings

settings用于MyBatis全局参数配置,这些是极其重要的调整,它们会修改 MyBatis 在运行时的行为方式。

里面各个属性的含义和默认值,用户文档已经说得比较清楚了,这儿不赘述了,把表格粘在下边儿。

MyBatis(四) —— MyBatis全局配置文件SqlMapConfig.xml中各属性详解_第2张图片

3. typeAliases

typeAliases 用于定义别名。从前面文章的例子可以看到,我们需要在配置文件中指定出入参类型,而且还是全路径,总是这样输入全路径会很不方便。

于是,我们可以为这个全路径定义一个别名,在后面的配置中就可以使用这个别名代替相关的全路径配置。配置也很简单,type属性中放置类的全路径,alias属性中放置代替这个全路径额别名,如下:

<typeAliases>
	<typeAlias alias="Pojo" type="com.mybatis.example.Pojo"/>
typeAliases>

另外,可以批量定义别名,批量定义时在package属性内填入包名,MyBatis自动扫描包中的类,生成的别名为类名(首字母大小写均可):

<typeAliases>
	<typeAlias package="com.mybatis.example"/>
typeAliases>

对于普通的 Java 类型,有许多内建的类型别名。它们都是大小写不敏感的,由于重载
的名字,要注意原生类型的特殊处理。

MyBatis(四) —— MyBatis全局配置文件SqlMapConfig.xml中各属性详解_第3张图片MyBatis(四) —— MyBatis全局配置文件SqlMapConfig.xml中各属性详解_第4张图片

4. typeHandler

无论是 MyBatis 在预处理语句中设置一个参数,还是从结果集中取出一个值时,类型处
理器被用来将获取的值以合适的方式转换成 Java 类型,typeHandler就充当这样的角色,用于完成jdbc类型和java类型的转换。

可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。要
这样做的话,简单实现 TypeHandler 接口( org.mybatis.type),然后映射新的类型处理器类到Java 类型,还有可选的一个 JDBC 类型。但是一般情况下,MyBatis提供的类型已经足够使用,不需要做自定义,因此,这里也不多展开了,详细可参考用户指南。

5. objectFactory

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 constructorArgTypes, List constructorArgs)。最终, setProperties 方法可以被用来配置ObjectFactory。在初始化ObjectFactory实例后,objectFactory元素体中定义的属性会被传递给 setProperties方法。

6. plugins

MyBatis 允许在某一点拦截已映射语句执行的调用,plugins就是用来拦截方法调用:

  • Executor(update, query, flushStatements, commit, rollback,
    getTransaction, close, isClosed)
  • ParameterHandler(getParameterObject, setParameters)
  • ResultSetHandler(handleResultSets, handleOutputParameters)
  • StatementHandler(prepare, parameterize, batch, update, query)

这些类中方法的详情可以通过查看每个方法的签名来发现,而且它们的源代码存在于
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”方法调用,它也是负责低层次
映射语句执行的内部对象。

7.environments

7.1 environment

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

7.2 transactionManager

transactionManager用于指定事务管理器类型。MyBatis提供了两种:

  • JDBC – 这个配置直接简单使用了 JDBC 的提交和回滚设置。它依赖于从数据源得 到的连接来管理事务范围。
  • MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让 容器来管理事务的整个生命周期(比如 SpringJEE 应用服务器的上下文)。默认 情况下它会关闭连接。然而一些容器并不希望这样,因此如果需要从连接中停止它,将closeConnection 属性设置为 false。例如:
<transactionManager type="MANAGED">
	<property name="closeConnection" value="false"/>
transactionManager>

这两种事务管理器都不需要任何属性。需要注意的是,JDBCMANAGED都是别名,如果需要传入自定义的类型,需要自己再定义别名或者传入类的全路径。自定义事务管理器需要实现两个接口:

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;
}

7.3 dataSource

dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。

MyBatis提供了三种内建的数据源类型:


  • UNPOOLED– 会每次请求时打开和关闭连接。速度上有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。性能表现则依赖于使用的数据库,对于是否使用连接池不重要的数据库来说,这个配置就很适合。UNPOOLED类型的数据源仅仅需要配置以下 5 种属性:
    • driver – 这是 JDBC 驱动的 Java 类全限定名;
    • url – 这是数据库的 JDBC URL 地址;
    • username – 登录数据库的用户名;
    • password – 登录数据库的密码;
    • defaultTransactionIsolationLevel – 默认的连接事务隔离级别;
    • defaultNetworkTimeout – 等待数据库操作完成的默认网络超时时间(单位: ms)。

作为可选项,你也可以传递属性给数据库驱动。只需在属性名加上“driver.”前缀即可,例如:driver.encoding=UTF8。这将通过 DriverManager.getConnection(url, driverProperties) 方法传递值为 UTF8encoding 属性给数据库驱动。


  • POOLED– 利用数据库连接池,避免创建和关闭l连接时不必要的时间和性能的开销。除了上述提到 UNPOOLED 下的属性外,还有更多属性用来配置 POOLED 的数据源:
    • poolMaximumActiveConnections – 在任意时间可存在的活动(正在使用)连接数量,默认值:10
    • poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。
    • poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000毫秒(即 20 秒)
    • poolTimeToWait – 一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直失败且不打印日志),默认值:20000 毫秒(即 20 秒)。
    • poolMaximumLocalBadConnectionTolerance – 一个关于坏连接容忍度的底层设置,作用于每一个尝试从缓存池获取连接的线程。如果这个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过poolMaximumIdleConnectionspoolMaximumLocalBadConnectionTolerance 之和。 默认值:3(新增于 3.4.5
    • poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”,这会引起许多数据库驱动连接由一个错误信息而导致失败。
    • poolPingEnabled – 是否启用侦测查询。若开启,需要设置 poolPingQuery 属性为一个可执行的 SQL语句(最好是一个速度非常快的 SQL 语句),默认值:false
    • poolPingConnectionsNotUsedFor – 配置 poolPingQuery的频率。可以被设置为和数据库连接超时时间一样,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当且仅当poolPingEnabledtrue 时适用)。

  • JNDI – 为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI上下文的数据源引用。这种数据源配置只需要两个属性:
  • initial_context – 这个属性用来在 InitialContext中寻找上下文(即,initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么将会直接从InitialContext 中寻找 data_source 属性。
  • data_source – 这是引用数据源实例位置的上下文路径。提供了 initial_context配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。

和其他数据源配置类似,可以通过添加前缀“env.”直接把属性传递给 InitialContext。比如:env.encoding=UTF8这就会在 InitialContext 实例化时往它的构造方法传递值为 UTF8encoding 属性。

可以通过实现接口 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();
  }
}

为了令其工作,记得在配置文件中增加对应的属性。

7.4 mappers

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.javaMapper.xml需要在同一目录下且名字相同(如同样在com/***/mapper包下的UserMapper.javaUserMapper.xml)。

当需要加载多个映射文件时,可以把这些映射文件放到同一个包里面,方便管理,同时也可以使用批量加载的方法一次性加载:

<mappers>
	<package name="com.***.mapper"/>
mappers>

name属性指定Mapper接口存在的包名,MyBatis会自动扫描所有的接口进行加载,需要遵守的规律如上一段所描述

8. 总结

本文介绍了MyBatis全局配置文件中的一些属性及一些常用的使用方法,其中高亮的部分属于比较常用且重要的内容。当然,里面还有很多内容没有展开,例如settings里面的其他设置、typeHandler的开发等,对于这些内容,可查阅MyBatis的手册查找相关的资料。

9.参考资料

【1】MyBatis User Guide
【2】传智 SpringMVC + MyBatis由浅入深 教程

你可能感兴趣的:(由浅及深)