Mybatis全局配置文件详解(三)

每个基于Mybatis应用都是以一个SqlSessionFactory实例为中心。SqlSessionFactory实例可以由SqlSessionFactoryBuild获得,而SqlSessionFactoryBuild可以以一个xml配置文件(Configuration.xml)构建出SqlSessionFactory实例。

Configuration.xml:

<?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>
    //...... 
</configuration>

</configuration>主要有以下几个标签:

  • <databaseIdProvider>
  • <environments>
  • <mappers>
  • <objectFactory>
  • <objectWrapperFactory>
  • <plugins>
  • <properties>
  • <reflectorFactory>
  • <settings>
  • <typeAliases>
  • <typeHandlers>

注意:mybatis全局配置文件的标签是有顺序限制的。

properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?

一、properties

作用:引用java属性文件中的配置信息,比如,加载连接数据库的各种属性的配置文件。

properties有两个属性:

  • resource 引入类路径下资源 
  • url 引入网络路径或磁盘路径下资源
<properties resource="jdbc.properties"></properties>

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.178.5:12345/ssm?useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai
jdbc.name=root
jdbc.password=123456

在配置文件中即可以使用类似${jdbc.name}来获取对应的属性值。

二、settings

用于改变Mybatis运行时的行为,比如开启二级缓存、开启延时加载等操作。

常见的配置如下:

<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="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <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>

1. cacheEnabled

该配置影响的所有映射器中配置的缓存的全局开关。可选值true或false,默认是true。

2. lazyLoadingEnabled

延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。可选值true或false,默认是false。

3. aggressiveLazyLoading

是否允许单一语句返回多结果集(需要兼容驱动)。

可选值true或false,默认是true。

4. useColumnLabel

使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。

可选值true或false,默认是true。

5. useGeneratedKeys

允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。

可选值true或false,默认是false。

6. autoMappingBehavior

指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。

可选值NONE, PARTIAL, FULL,默认是PARTIAL。

7. defaultExecutorType

配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。

可选值SIMPLE, REUSE, BATCH,默认是SIMPLE 。

8. defaultStatementTimeout

设置超时时间,它决定驱动等待数据库响应的秒数。

9. safeRowBoundsEnabled

允许在嵌套语句中使用分页(RowBounds)。

可选值true或false,默认是false。

10. mapUnderscoreToCamelCase

是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。

可选值true或false,默认是false。

11. localCacheScope

MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。

可选值SESSION,STATEMENT,默认是SESSION。

12. jdbcTypeForNull

当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。

默认是OTHER。

13. lazyLoadTriggerMethods

指定哪个对象的方法触发一次延迟加载。

默认是equals,clone,hashCode,toString。

14. defaultScriptingLanguage

指定动态 SQL 生成的默认语言。

默认是org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver。

15. callSettersOnNulls

指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。

可选值true或false,默认是false。

16. logPrefix

指定 MyBatis 增加到日志名称的前缀。

17. logImpl

指定 MyBatis 所用日志的具体实现,未指定时将自动查找。

可选值SLF4J,LOG4J,LOG4J2,JDK_LOGGING,COMMONS_LOGGING,STDOUT_LOGGING,NO_LOGGING,没有默认值。

18. proxyFactory

指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。

可选值CGLIB, JAVASSIST,默认值CGLIB。

三、typeAliases

类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。

例如:

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

当这样配置时,Blog可以用在任何使用domain.blog.Blog的地方。

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

<typeAliases>
  <package name="domain.blog"/>
</typeAliases>

每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;若有注解,则别名为其注解值。看下面的例子:

@Alias("author")
public class Author {
     ...
}

已经为许多常见的 Java 类型内建了相应的类型别名。它们都是大小写不敏感的,需要注意的是由基本类型名称重复导致的特殊处理。

  _byte     byte  
  _long     long  
  _short     short  
  _int     int  
  _integer     int  
  _double     double  
  _float     float  
  _boolean     boolean  
  string     String  
  byte     Byte  
  long     Long  
  short     Short  
  int     Integer  
  integer     Integer  
  double     Double  
  float     Float  
  boolean     Boolean  
  date     Date  
  decimal     BigDecimal  
  bigdecimal     BigDecimal  
  object     Object  
  map     Map  
  hashmap     HashMap  
  list     List  
  arraylist     ArrayList  
  collection     Collection  
  iterator     Iterator  

四、typeHandlers

无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。

类型处理器 Java 类型 JDBC 类型
BooleanTypeHandler java.lang.Booleanboolean 数据库兼容的 BOOLEAN
ByteTypeHandler java.lang.Bytebyte 数据库兼容的 NUMERIC 或 BYTE
ShortTypeHandler java.lang.Shortshort 数据库兼容的 NUMERIC 或 SHORT INTEGER
IntegerTypeHandler java.lang.Integerint 数据库兼容的 NUMERIC 或 INTEGER
LongTypeHandler java.lang.Longlong 数据库兼容的 NUMERIC 或 LONG INTEGER
FloatTypeHandler java.lang.Floatfloat 数据库兼容的 NUMERIC 或 FLOAT
DoubleTypeHandler java.lang.Doubledouble 数据库兼容的 NUMERIC 或 DOUBLE
BigDecimalTypeHandler java.math.BigDecimal 数据库兼容的 NUMERIC 或 DECIMAL
StringTypeHandler java.lang.String CHARVARCHAR
ClobTypeHandler java.lang.String CLOBLONGVARCHAR
NStringTypeHandler java.lang.String NVARCHARNCHAR
NClobTypeHandler java.lang.String NCLOB
ByteArrayTypeHandler byte[] 数据库兼容的字节流类型
BlobTypeHandler byte[] BLOBLONGVARBINARY
DateTypeHandler java.util.Date TIMESTAMP
DateOnlyTypeHandler java.util.Date DATE
TimeOnlyTypeHandler java.util.Date TIME
SqlTimestampTypeHandler java.sql.Timestamp TIMESTAMP
SqlDateTypeHandler java.sql.Date DATE
SqlTimeTypeHandler java.sql.Time TIME
ObjectTypeHandler Any OTHER 或未指定类型
EnumTypeHandler Enumeration Type VARCHAR-任何兼容的字符串类型,存储枚举的名称(而不是索引)
EnumOrdinalTypeHandler Enumeration Type 任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的索引(而不是名称)。

你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler, 然后可以选择性地将它映射到一个 JDBC 类型。

五、objectFactory

我们在使用MyBatis执行查询语句的时候,通常都会有一个返回类型,这个是在mapper文件中给sql增加一个resultType(或resultMap)属性进行控制。resultType和resultMap都能控制返回类型,只要定义了这个配置就能自动返回我想要的结果,MyBatis在创建结果集的时候,会使用其定义的对象工厂DefaultObjectFactory来完成对应的工作。

我们也可以继承DefaultObjectFactory自定义。

六、objectWrapperFactory

 待续......

七、reflectorFactory

  待续......

八、plugins

MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

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

通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定了想要拦截的方法签名即可。

九、environments

<!-- default指定的是当前使用的环境 -->
<environments default="default">
    <!-- 声明可能使用到的环境 -->
    <environment id="default">
        <!-- 使用原生的JDBC事务,默认是自动提交的 -->
        <transactionManager type="JDBC"></transactionManager>
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driver}" />
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.name}" />
            <property name="password" value="${jdbc.password}" />
        </dataSource>
    </environment>
</environments>

1. 事务管理器(transactionManager)

在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):

(1) JDBC:这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务范围。

(2) MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。例如:

<transactionManager type="MANAGED">
     <property name="closeConnection" value="false"/>
</transactionManager>

2. 数据源(dataSource)

有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):

(1) UNPOOLED

这个数据源的实现只是每次被请求时打开和关闭连接。UNPOOLED 类型的数据源仅仅需要配置以下 5 种属性:

  • driver:JDBC 驱动的 Java 类的完全限定名
  • url:数据库的 JDBC URL 地址
  • username:登录数据库的用户名
  • password:登录数据库的密码
  • defaultTransactionIsolationLevel :默认的连接事务隔离级别

(2) POOLED

这种数据源的实现利用"池"的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这是一种使得并发 Web 应用快速响应请求的流行处理方式。

除了上述提到 UNPOOLED 下的属性外,会有更多属性用来配置 POOLED 的数据源:

  • poolMaximumActiveConnections:在任意时间可以存在的活动(也就是正在使用)连接数量,默认值:10。
  • poolMaximumIdleConnections:任意时间可能存在的空闲连接数。
  • poolMaximumCheckoutTime:在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)。
  • poolTimeToWait:这是一个底层设置,如果获取连接花费的相当长的时间,它会给连接池打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直安静的失败),默认值:20000 毫秒(即 20 秒)。
  • poolPingQuery:发送到数据库的侦测查询,用来检验连接是否处在正常工作秩序中并准备接受请求。默认是"NO PING QUERY SET",这会导致多数数据库驱动失败时带有一个恰当的错误消息。
  • poolPingEnabled:是否启用侦测查询。若开启,也必须使用一个可执行的 SQL 语句设置poolPingQuery 属性(最好是一个非常快的 SQL),默认值:false。
  • poolPingConnectionsNotUsedFor:配置 poolPingQuery 的使用频度。这可以被设置成匹配具体的数据库连接超时时间,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。

(3) JNDI

这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。这种数据源配置只需要两个属性:

  • initial_context:这个属性用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么 data_source 属性将会直接从 InitialContext 中寻找。
  • data_source:这是引用数据源实例位置的上下文的路径。提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。

通过需要实现接口 org.apache.ibatis.datasource.DataSourceFactory , 也可使用任何第三方数据源:

public interface DataSourceFactory {
      void setProperties(Properties props);
      DataSource getDataSource();
}

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

连接至 PostgreSQL 数据库的例子:

<dataSource type="org.myproject.C3P0DataSourceFactory">
   <property name="driver" value="org.postgresql.Driver"/>
   <property name="url" value="jdbc:postgresql:mydb"/>
   <property name="username" value="postgres"/>
   <property name="password" value="root"/>
</dataSource>

十、databaseIdProvider

databaseIdProvider的作用就是指定多个数据库厂商,mybatis进行切换到其他数据时可以动态的指定SQL语句进行执行。

<!-- 
    databaseIdProvider:支持多数据库厂商的;
    DB_VENDOR:VendorDatabaseIdProvider
    作用就是得到数据库厂商的标识(驱动getDatabaseProductName()),mybatis就能根据数据库厂商标识来执行不同的sql;
    MySQL,Oracle,SQL Server,xxxx
-->
<databaseIdProvider type="DB_VENDOR">
    <!-- 为不同的数据库厂商起别名 -->
    <property name="MySQL" value="mysql"/>
    <property name="Oracle" value="oracle"/>
    <property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>

databaseIdProvider子标签的value(mysql、oracle等)对应映射文件的databaseId。

<select id="getUserById" resultType="com.linhw.demo.pojo.User">
    select * from user where user_id = #{userId}
</select>
<select id="getUserById" resultType="com.linhw.demo.pojo.User" databaseId="mysql">
    select * from user where user_id = #{userId}
</select>
<select id="getUserById" resultType="com.linhw.demo.pojo.User" databaseId="oracle">
    select USER_ID userId,USER_NAME userName,AGE age
    from USER where USER_ID=#{userId}
</select>

说明:

databaseId值为mysql表示:当数据库连接为mysql数据库时,该语句才会被执行,如果此时项目使用的是orcle数据则该条语句不会被执行。

没有设置databaseId表示:无论当前连接的什么数据库,该条语句都能被使用。但是如上面这种情况,如果使用的mysql数据库则databaseId=mysql且id为getUserById的语句可以执行,而同时id也是getUserById且没指定的databaseId的语句也可以被执行。这时系统将执行指定更加精确的databaseId=mysql且id为getUserById的语句。

十一、mappers

使用<mapper>元素元素指定Mybatis映射文件的位置。有以下4中引入映射文件的方式。

1. 使用类路径

<!-- Using classpath relative resources -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>

2. 使用完全限定资源定位符

<!-- Using url fully qualified paths -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>

3. 使用接口类

<!-- Using mapper interface classes -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

4. 使用包引入

<mappers>
  <package name="org.mybatis.builder"/>
</mappers>