MyBatis 的 XML 配置文件包含了影响 MyBatis 行为甚深的设置和属性信息。 XML 文档
的高层级结构如下:
这些是外部化的,可替代的属性,这些属性也可以配置在典型的 Java 属性配置文件中,或者通过 properties 元素的子元素来传递。例如:
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
properties>
其中的属性就可以在整个配置文件中使用,使用可替换的属性来实现动态配置。比如:
这些是极其重要的调整,它们会修改 MyBatis 在运行时的行为方式。下面这个表格描述
了设置信息,它们的含义和默认值。
设置参数 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 这个配置使全局的映射器启用或禁用 缓存。 | true | false | true |
lazyLoadingEnabled | 全局启用或禁用延迟加载。 当禁用时, 所有关联对象都会即时加载。 | true | false | true |
aggressiveLazyLoading | 当启用时,有延迟加载属性的对象在被 调用时将会完全加载任意属性。否则, 每种属性将会按需要加载。 | true | false | true |
multipleResultSetsEnabled | 允许或不允许多种结果集从一个单独 的语句中返回(需要适合的驱动)。 | true | false | true |
useColumnLabel | 使用列标签代替列名。不同的驱动在这 方便表现不同。参考驱动文档或充分测 试两种方法来决定所使用的驱动。 | true | false | true |
useGeneratedKeys | 允许 JDBC 支持生成的键。需要适合的 驱动。如果设置为 true 则这个设置强制 生成的键被使用,尽管一些驱动拒绝兼 容但仍然有效(比如 Derby)。 | true | false | false |
autoMappingBehavior | 指定 MyBatis 如何自动映射列到字段/ 属性。 PARTIAL 只会自动映射简单, 没有嵌套的结果。 FULL 会自动映射任 意复杂的结果(嵌套的或其他情况)。 | NONE, PARTIAL, FULL | PARTIAL |
defaultExecutorType | 配置默认的执行器。 SIMPLE 执行器没 有什么特别之处。 REUSE 执行器重用 预处理语句。 BATCH 执行器重用语句 和批量更新 | SIMPLE, REUSE, BATCH | SIMPLE |
defaultStatementTimeout | 设置超时时间,它决定驱动等待一个数 据库响应的时间。 | 任 何 正 整 数 | Not Set (null) |
一个设置信息元素的示例,完全的配置如下所示:
<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="enhancementEnabled" value="false"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25000"/>
settings>
类型别名是为 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>
无论是 MyBatis 在预处理语句中设置一个参数,还是从结果集中取出一个值时,类型处
理器被用来将获取的值以合适的方式转换成 Java 类型。下面这个表格描述了默认的类型处理器。
类型处理器 | Java类型 | JDBC类型 |
---|---|---|
BooleanTypeHandler | Boolean, boolean | 任何兼容的布尔值 |
BooleanTypeHandler | Boolean, boolean | 任何兼容的布尔值 |
ShortTypeHandler | Short, short | 任何兼容的数字或短整型 |
IntegerTypeHandler | Integer, int | 任何兼容的数字和整型 |
LongTypeHandler | Long, long | 任何兼容的数字或长整型 |
FloatTypeHandler | Float, float | 任何兼容的数字或单精度浮点型 |
DoubleTypeHandler | Double, double | 任何兼容的数字或双精度浮点型 |
BigDecimalTypeHandler | BigDecimal | 任何兼容的数字或十进制小数类型 |
StringTypeHandler | String | CHAR 和 VARCHAR 类型 |
ClobTypeHandler | String | CLOB 和 LONGVARCHAR 类型 |
NStringTypeHandler | String | NVARCHAR 和 NCHAR 类型 |
NClobTypeHandler | String | NCLOB 类型 |
ByteArrayTypeHandler | byte[] | 任何兼容的字节流类型 |
BlobTypeHandler | byte[] | BLOB 和 LONGVARBINARY 类型 |
DateTypeHandler | Date(java.util) | TIMESTAMP 类型 |
DateOnlyTypeHandler | Date(java.util) | DATE 类型 |
TimeOnlyTypeHandler | Date(java.util) | TIME 类型 |
SqlTimestampTypeHandler | Timestamp(java.sql) | TIMESTAMP 类型 |
SqlDateTypeHandler | Date(java.sql) | DATE 类型 |
SqlTimeTypeHandler | Time(java.sql) | TIME 类型 |
ObjectTypeHandler | 任意 | 其他或未指定类型 |
EnumTypeHandler | Enumeration 类型 | VARCHAR-任何兼容的字符串类型, 作为代码存储(而不是索引)。 |
你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。要这样做的话,简单实现 TypeHandler 接口(org.mybatis.type),然后映射新的类型处理器类到Java 类型,还有可选的一个 JDBC 类型。例如:
// ExampleTypeHandler.java
public class ExampleTypeHandler implements TypeHandler {
public void setParameter(PreparedStatement ps, int i, Objectparameter,JdbcType jdbcType) throws SQLException {
ps.setString(i, (String) parameter);
}
public Object getResult(ResultSet rs, String columnName)
throws SQLException {
return rs.getString(columnName);
}
public Object getResult(CallableStatement cs, int columnIndex)
throws SQLException {
return cs.getString(columnIndex);
}
}
// MapperConfig.xml
<typeHandlers>
<typeHandler javaType="String" jdbcType="VARCHAR"
handler="org.mybatis.example.ExampleTypeHandler"/>
typeHandlers>
使用这样的类型处理器将会覆盖已经存在的处理 Java 的 String 类型属性和 VARCHAR参数及结果的类型处理器。要注意 MyBatis 不会审视数据库元信息来决定使用哪种类型,所以你必须在参数和结果映射中指定那是 VARCHAR 类型的字段,来绑定到正确的类型处理器上。 这是因为 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);
}
}
// MapperConfig.xml
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
<property name="someProperty" value="100"/>
objectFactory>
ObjectFactory 接口非常简单。它包含两个用于创建的方法,一个是默认构造方法,另外一个是处理带参数的构造方法。最终, setProperties 方法可以被用来配置 ObjectFactory。在初始化你的ObjectFactory实例后, objectFactory元素体中定义的属性会被传递给setProperties方法 。
MyBatis 允许你在某一点拦截已映射语句执行的调用。默认情况下, 允许使用插件来拦截方法调用:
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”方法调用,它也是负责低层次
映射语句执行的内部对象。
覆盖配置类
除了用插件来修改 MyBatis 核心行为之外,你也可以完全覆盖配置类。简单扩展它,
然后覆盖其中的任意方法,之后传递它的sqlSessionFactoryBuilder.build(myConfig)方法的调用。这可能会严重影响 MyBatis 的行为,所以要小心。
MyBatis 可以配置多种环境。这会帮助你将 SQL 映射应用于多种数据库之中。例如,你也许为开发要设置不同的配置,测试和生产环境。或者你可能有多种生产级数据库却共享相同的模式,所以你会想对不同数据库使用相同的 SQL 映射。这种用例是很多的。
要记得一个很重要的问题:你可以配置多种环境,但你只能为每个SqlSessionFactory实例选择一个。
所以,如果你想连接两个数据库,你需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,你就需要三个实例,以此类推。记忆起来很简单:
环境元素定义了如何配置环境。
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
dataSource>
environment>
environments>
注意这里的关键部分:
默认的环境 ID(比如: default=”development”)。
每个 environment 元素定义的环境 ID(比如: id=”development”)。
事务管理器的配置(比如: type=”JDBC”)。
数据源的配置(比如: type=”POOLED”)。
默认的环境和环境 ID 是自我解释的。你可以使用你喜欢的名称来命名,只要确定默认
的要匹配其中之一。
在 MyBatis 中有两种事务管理器类型(也就是 type=”[JDBC|MANAGED]”):
JDBC – 这个配置直接简单使用了 JDBC 的提交和回滚设置。它依赖于从数据源得到的连接来管理事务范围。
MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让容器来管理事务的整个生命周期(比如 Spring 或 JEE 应用服务器的上下文)。默认情况下它会关闭连接。然而一些容器并不希望这样,因此如果你需要从连接中停止它,将 closeConnection 属性设置为 false。例如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
transactionManager>
这两种事务管理器都不需要任何属性。然而它们都是类型别名,要替换使用它们,你需要放置将你自己的类的完全限定名或类型别名,它们引用了你对 TransacFactory 接口的实现类。
public interface TransactionFactory {
void setProperties(Properties props);
Transaction newTransaction(Connection conn, boolean autoCommit);
}
任何在 XML 中配置的属性在实例化之后将会被传递给 setProperties()方法。你的实现类需要创建一个事务接口的实现,这个接口也很简单:
public interface Transaction {
Connection getConnection();
void commit() throws SQLException;
void rollback() throws SQLException;
void close() throws SQLException;
}
使用这两个接口,你可以完全自定义 MyBatis 对事务的处理。
dataSource 元素使用基本的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
有三种内建的数据源类型(也就是 type=”???”):
UNPOOLED – 这个数据源的实现是每次被请求时简单打开和关闭连接。它有一点慢,这是对简单应用程序的一个很好的选择,因为它不需要及时的可用连接。不同的数据库对这个的表现也是不一样的,所以对某些数据库来说配置数据源并不重要,这个配置也是闲置的。UNPOOLED 类型的数据源仅仅用来配置以下 5 种属性:
作为可选项,你可以传递数据库驱动的属性。要这样做,属性的前缀是以“”开
头的,例如:
这 样 就 会 传 递 以 值 “ UTF8 ” 来 传 递 “ encoding ” 属 性 , 它 是 通 过DriverManager.getConnection(url,driverProperties)方法传递给数据库驱动。
POOLED – 这是 JDBC 连接对象的数据源连接池的实现,用来避免创建新的连接实例时必要的初始连接和认证时间。这是一种当前 Web 应用程序用来快速响应请求很流行的方法。
除了上述(UNPOOLED)的属性之外,还有很多属性可以用来配置 POOLED 数据源:
JNDI – 这个数据源的实现是为了使用如 Spring 或应用服务器这类的容器,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。这个数据源配置只需要两个属性:
initial_context – 这 个 属 性 用 来 从 初 始 上 下 文 中 寻 找 环 境 ( 也 就 是initialContext.lookup( initial——context))。这是个可选属性,如果被忽略,那么data_source 属性将会直接以 initialContext 为背景再次寻找。
data_source – 这是引用数据源实例位置的上下文的路径。它会以由initial_context查询返回的环境为背景来查找,如果 initial_context 没有返回结果时,直接以初始上下文为环境来查找。和其他数据源配置相似,它也可以通过名为“env.”的前缀直接向初始上下文发送属性。比如:
env.encoding=UTF8
在初始化之后, 这就会以值“ UTF8”向初始上下文的构造方法传递名为“encoding”的属性。
既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要定义 SQL 映射语句了。
但是,首先我们需要告诉 MyBatis 到哪里去找到这些语句。 Java 在这方面没有提供一个很好的方法,所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。你可以使用相对于类路径的资源引用,或者字符表示,或 url 引用的完全限定名(包括 file:///URLs)。例如:
// 使用相对于类路径的资源
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
mappers>
// 使用完全限定路径
<mappers>
<mapper url="file:///var/sqlmaps/AuthorMapper.xml"/>
<mapper url="file:///var/sqlmaps/BlogMapper.xml"/>
<mapper url="file:///var/sqlmaps/PostMapper.xml"/>
mappers>
这些语句简单告诉了 MyBatis 去哪里找映射文件。其余的细节就是在每个 SQL 映射文
件中了 。