configuration
MyBatis配置包含了对MyBatis的行为有显著影响的设置和属性。xml配置文件的根元素起始标签为<configuration/> ,configuration下有以下可配置的子元素:
1. properties
properties可以可以配置一些属性值,也可以通过properties的resource、url属性引入外部的属性配置。然后,这些属性可以在整个配置文件中用来替代需要动态配置的值。
例如:
<properties resource="config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="123456"/>
</properties>
在使用时,通过${}符号取值,通过这种方式还可以为属性配置默认值,例如:
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<!--配置默认值,若通过${}符号取值为空,则填充默认值ut_user,这个默认值功能默认是关闭的,
需要在properties元素中添加子元素开启
<property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>-->
<property name="username" value="${username:ut_user}"/>
<property name="password" value="${password}"/>
</dataSource>
在获取属性值时,mybatis还可以通过直接将属性配置文件作为参数传入SqlSessionFactoryBuilder.build()方法中,例如:
SqlSessionFactory factory =
sqlSessionFactoryBuilder.build(reader, props);
// ... or ...
SqlSessionFactory factory =
new SqlSessionFactoryBuilder.build(reader, environment, props);
注意:以上3中配置属性值的方法的优先级为:
- 在properties元素中的<property/>标签中指定的属性被首先读取。
- 从properties元素中resource属性或url属性中加载的属性将被二次读取,并覆盖任何已经指定的重复属性。
- 作为方法参数传入的属性会被最后读取,并覆盖任何可能已经从属性元素和资源/url属性加载的重复属性。
因此,优先级最高的属性是作为方法参数传入的属性,其次是resource/url中加载的属性,最后是properties元素中的<property/>标签中指定的属性。
2. settings
settings元素是mybatis中比较重要的配置,这些配置会影响MyBatis在运行时的行为方式。以下描述了所有的这些设置、及它们的含义,value表示它们的默认值。
<settings>
<!--全局启用或禁用任何mapper中配置的任何缓存。默认为true-->
<setting name="cacheEnabled" value="true"/>
<!--全局地启用或禁用懒加载。当启用时,所有的关系将被延迟加载。可以通过使用fetchType属性来取代全局配置。-->
<setting name="lazyLoadingEnabled" value="false"/>
<!--允许或不允许从一条语句中返回多个结果集(需要兼容的驱动程序)-->
<setting name="multipleResultSetsEnabled" value="true"/>
<!--使用列标签而不是列名。不同的驱动程序在这方面有不同的表现。请参阅驱动程序文档,或测试两种模式以确定您的驱动程序的行为。-->
<setting name="useColumnLabel" value="true"/>
<!--允许支持生成密钥的JDBC。需要一个兼容的驱动程序。如果设置为 "true",则会强制使用生成的密钥,即使有些驱动程序不兼容,但仍然可以工作(例如Derby)。-->
<setting name="useGeneratedKeys" value="false"/>
<!--指定MyBatis是否以及如何自动将列映射到字段/属性。
NONE 禁用自动映射。
PARTIAL只会自动映射内部没有定义嵌套的结果。
FULL将自动映射任何复杂性(包含嵌套或其他)的结果映射。-->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<!-- 指定检测到自动映射目标的未知列(或未知属性类型)时的行为。
NONE: 什么也不做
WARNING:输出warning日志
FAILING: 映射失败(抛出SqlSessionException异常)
-->
<setting name="autoMappingUnknownColumnBehavior" value="NONE"/>
<!--配置默认的executor
SIMPLE executor不做任何特别的事情。
REUSE executor重用prepared statements。
BATCH executor重用prepared statements并批量更新。
-->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!--设置驱动程序等待数据库响应的秒数。默认没有设置-->
<setting name="defaultStatementTimeout" value=""/>
<!--设置控制返回结果的数量。这个参数值可以通过查询设置来覆盖。默认没有设置-->
<setting name="defaultFetchSize" value=""/>
<!--根据语句设置省略时指定的scroll策略(Since: 3.5.2)。默认没有设置
FORWARD_ONLY |
SCROLL_SENSITIVE |
SCROLL_INSENSITIVE |
DEFAULT(same behavior
with 'Not Set')
-->
<setting name="defaultResultSetType" value=""/>
<!--是否允许在嵌套语句上使用RowBounds。如果允许,则设置为false。 -->
<setting name="safeRowBoundsEnabled" value="false"/>
<!--允许在嵌套statements上使用ResultHandler。如果允许,则设置为false。-->
<setting name="safeResultHandlerEnabled" value="True"/>
<!--启用数据库列名从下划线格式(A_COLUMN类型)到Java属性名驼峰命名(aColumn)的自动映射 -->
<setting name="mapUnderscoreToCamelCase" value="false"/>
<!--MyBatis使用本地缓存来防止循环引用和加快重复嵌套查询。
SESSION:会话期间执行的所有查询都会被缓存。
STATEMENT:本地session将只用于语句执行,同一SqlSession的两个不同调用之间不会共享数据。 -->
<setting name="localCacheScope" value="SESSION"/>
<!--当没有为参数提供特定的JDBC类型时,为空值指定JDBC类型。有些驱动程序要求指定列的JDBC类型,但其他驱动程序则使用通用值,如NULL、VARCHAR或其他。-->
<setting name="jdbcTypeForNull" value="OTHER"/>
<!--指定Object的哪些方法会触发懒加载。-->
<setting name="lazyLoadTriggerMethods"
value="equals,clone,hashCode,toString"/>
<!-- 指定动态SQL生成时默认使用的语言。-->
<setting name="defaultScriptingLanguage" value="org.apache.ibatis.scripting.xmltags.XMLLanguageDriver"/>
<!-- 指定Enum类型的处理器 (Since:3.4.5)-->
<setting name="defaultEnumTypeHandler" value="org.apache.ibatis.type.EnumTypeHandler"/>
<!-- 指定当检索到的值为空时,是否会调用setters或map的put方法。
当您依赖 Map.keySet() 或空值初始化时,它很有用。请注意,(int,boolean等)等基元不会被设置为空值。-->
<setting name="callSettersOnNulls" value="false"/>
<!--默认情况下,当返回行的所有列都是NULL时,MyBatis返回null。当启用此设置时,MyBatis将返回一个空实例。
请注意,它也适用于嵌套结果(即collectioin和关联)。Since: 3.4.2 -->
<setting name="returnInstanceForEmptyRow" value="false"/>
<!-- 指定MyBatis将添加到logger名称的前缀字符串。默认未设置-->
<setting name="logPrefix" value=""/>
<!--指定MyBatis应该使用的日志实现。如果此设置不存在,将自动发现日志实现。默认未设置
SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING
-->
<setting name="logImpl" value=""/>
<!-- 指定MyBatis将使用的代理工具,用于创建能够懒加载的对象。CGLIB | JAVASSIST -->
<setting name="proxyFactory" value="JAVASSIST (MyBatis 3.3
or above)"/>
<!--指定 VFS的实现 默认未设置-->
<setting name="vfsImpl" value=""/>
<!--允许用方法签名中声明的实际名称来引用语句参数。要使用这个功能,你的项目必须在Java 8中使用-parameters选项编译。(自:3.4.1起)-->
<setting name="useActualParamName" value="true"/>
<!--指定提供Configuration实例的类。返回的 Configuration 实例用于加载反序列化对象的懒惰属性。这个类必须有一个签名为static Configuration getConfiguration()的方法。
(since:3.2.3) 默认未设置-->
<setting name="configurationFactory" value=""/>
</settings>
注意:在spring-mybatis中可通过在Spring的配置文件中指定mybatis.configuration前缀进行配置,例如:
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.call-setters-on-nulls=true
3.typeAliases
与java里面的@Alias注解作用类似,类型别名只是一个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将在其中搜索对应别名的bean。
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
4. typeHandlers
每当MyBatis在PreparedStatement上设置一个参数或从ResultSet中检索一个值时,就会使用TypeHandler以适合Java类型的方式处理该值。mybatis中有默认的TypeHandlers去处理相应的类型值。
但我们也可以自定义TypeHandle覆盖默认的TypeHandler,或创建TypeHandler来处理不支持的或非标准类型。要做到这一点,实现接口org.apache.ibatis.type.TypeHandler或继承类org.apache.ibatis.type.BaseTypeHandler,并可选地将其映射到一个JDBC类型。例如:
// ExampleTypeHandler.java
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ExampleTypeHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
String parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, parameter);
}
@Override
public String getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return rs.getString(columnName);
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
return rs.getString(columnIndex);
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return cs.getString(columnIndex);
}
}
然后在配置文件中添加如下配置:
<typeHandlers>
<typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>
<!--或者指定packages-->
<typeHandlers>
<package name="org.mybatis.example"/>
</typeHandlers>
这个TypeHandler将覆盖现有的Java String属性和VARCHAR类型参数/结果映射的处理。请注意,MyBatis不对数据库元数据进行反省以确定类型,所以您必须在参数和结果映射中指定它是一个VARCHAR字段,以获取正确的TypeHandler。
mybatis可以通过TypeHandler的泛型来确定要处理的java类型,但也可以通过在TypeHandler添加属性javaType(例如:javaType="String")或注解@MappedType (会覆盖javaType中的类型)来指定要处理的java类型。
相应的通过在TypeHandler添加属性jdbcType(例如:jdbcType="VARCHAR")或注解@MappedJdbcTypes (会覆盖jdbcType中的类型)来指定要处理的jdbc类型。
5. objectFactory
每次MyBatis创建一个新的结果对象实例时,它都会使用一个ObjectFactory实例来完成。默认的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);
}
public <T> boolean isCollection(Class<T> type) {
return Collection.class.isAssignableFrom(type);
}}
然后在配置文件中配置:
<!-- mybatis-config.xml -->
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
<property name="someProperty" value="100"/>
</objectFactory>
6.plugins
MyBatis允许在执行sql语句前后某些点自定义拦截器。
默认情况下,MyBatis允许插件拦截以下方法的调用。
- - Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- - ParameterHandler(getParameterObject, setParameters)
- - ResultSetHandler(handleResultSets, handleOutputParameters)
- - StatementHandler (prepare, parameterize, batch, update, query)
考虑到插件提供的功能,使用插件是非常简单的。只需实现拦截器接口,一定要指定您要拦截的方法签名。
// ExamplePlugin.java,需要指定要拦截的方法等签名
@Intercepts({@Signature(
type= Executor.class,
method = "update",
args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
private Properties properties = new Properties();
public Object intercept(Invocation invocation) throws Throwable {
// implement pre processing if need
Object returnObject = invocation.proceed();
// implement post processing if need
return returnObject;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
然后在配置文件中配置对应的拦截器:
<plugins>
<plugin interceptor="org.mybatis.example.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
7. environments
MyBatis可以配置多个环境。这有助于您出于任何原因将您的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>
可以为不同的环境配置不同的<enviroment/>,在使用时指定<environments default="development">其中一个<enviroment/>的id即可。
7.1 transactionManager:
mybatis中包含2种类型的transactionManager,type="[JDBC|MANAGED]"。
- JDBC:这种配置只是直接使用JDBC自带的提交和回滚功能。它依靠从dataSource获取的连接来管理事务的范围。
- MANAGED 这种配置几乎什么都不做。它从不提交或回滚connection。相反,它让容器管理事务的整个生命周期(如JEE应用服务器上下文)。默认情况下,它确实会关闭connection。然而,有些容器并不希望这样,因此,如果你需要阻止它关闭连接,请将 "closeConnection "属性设置为false。例如:
<transactionManager type="MANAGED">。
<property name="closeConnection" value="false"/>。
</transactionManager>
注意:如果您计划在Spring中使用MyBatis,则不需要配置任何TransactionManager,因为Spring模块将设置自己的TransactionManager,覆盖任何先前设置的配置。
这些TransactionManager类型都不需要任何属性。然而,它们都是类型别名,所以换句话说,你可以不使用它们,而是放上你自己的完全限定的类名或类型别名,指向你自己的TransactionFactory接口的实现。使用TransactionFactory和Transaction这两个接口,您可以完全自定义MyBatis如何处理事物。
7.2 dataSource
dataSource元素使用标准的JDBC DataSource接口配置JDBC连接对象的源。有三种内置的数据源类型(即type=[UNPOOLED|POOLED|JNDI])可以配置。
- UNPOOLED:DataSource的这种实现是在每次请求时打开和关闭一个连接。速度较慢,适用于对性能要求不高的简单应用,UNPOOLED DataSource有以下属性需要配置:
driver:驱动
url:数据库实例的JDBC URL
username : 数据库用户名。
password :数据库密码。
defaultTransactionIsolationLevel: 连接的默认事务隔离级别。
defaultNetworkTimeout : 默认的网络超时值,单位为毫秒。来等待数据库操作的完成。
- POOLED:配置DataSource的连接池,以避免创建一个新的Connection实例所需的初始连接和验证时间。对于并发的Web应用程序来说,这是一种高效的方法,可以实现最快的响应。
除了上面的(UNPOOLED)属性外,还有更多的属性可以用来配置POOLED数据源。
poolMaximumActiveConnections :最大活跃(即使用中)连接数。默认值: 10
poolMaximumIdleConnections :最大空闲连接数。
poolMaximumCheckoutTime : Connection从连接池取出的最大使用时间,超过则会被强制收回。默认值: 20000ms (即20秒)
poolTimeToWait: 这是一个低级别的设置,它使连接池有机会打印日志状态,并在花费特别长的时间的情况下重新尝试获取连接(以避免在连接池配置错误的情况下永远默默地失败)。默认值:20000ms(即20秒)
poolMaximumLocalBadConnectionTolerance:这是一个关于任何线程的坏连接容忍度的低级设置。如果一个线程得到了一个坏的连接,它仍然有机会重新尝试得到另一个有效的连接。但是重试的次数不能超过 poolMaximumIdleConnections 和 poolMaximumLocalBadConnectionTolerance 之和。默认值: 3 (自: 3.4.5起)
poolPingQuery: 向数据库发送Ping查询,以验证连接是否处于良好的工作状态,并准备接受请求。默认值是 "NO PING QUERY SET",这将导致大多数数据库驱动程序失败,并给出一个不错的错误信息。
poolPingEnabled :这将启用或禁用ping查询。如果启用,你必须使用有效的SQL语句(最好是一个非常快的语句)来设置poolPingQuery属性。默认值:false。 poolPingConnectionsNotUsedFor:这配置了 poolPingQuery 的使用频率。这可以设置为与数据库连接的典型超时相匹配,以避免不必要的ping。默认值:0 (即所有连接每次都会被ping,当然只有当poolPingEnabled为true时才会被ping)。
- JNDI: DataSource的这一实现旨在与容器(如EJB或应用服务器)一起使用,这些容器可以集中或从外部配置DataSource,并在JNDI上下文中放置对它的引用。这种DataSource配置只需要两个属性。
initial_context :这个属性用于从InitialContext中查找Context(即initialContext.lookup(initial_context))。这个属性是可选的,如果省略了这个属性,那么将直接针对InitialContext来查找data_source属性。
data_source :这是可以找到 DataSource 实例引用的上下文路径。它将根据 initial_context lookup 返回的上下文进行查找,如果没有提供 initial_context,则直接根据 InitialContext 进行查找。
除了上述配置的3种类型的数据源,你也可以通过实现接口org.apache.ibatis.datasource.DataSourceFactory来使用任何第三方DataSource。
8.mappers
MyBatis的行为通过上述配置元素配置完成,最后一步是需要告诉MyBatis在哪里找到SQL语句。在这方面,Java并没有真正提供任何好的自动发现手段,所以最好的方法是简单地告诉MyBatis在哪里找到映射文件。您可以使用classpath相对资源引用、完全限定的url引用(包括file:///URLs)、类名或包名。
<!-- 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>
<!-- 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>
<!-- Using mapper interface classes -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- Register all interfaces in a package as mappers -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
备注:文章内容翻译自mybatis官方文档《mybatis-Configuration XML》