前言
SqlMapConfig.xml文件是mybatis的核心配置文件,mybatis框架在管理数据层的过程中首先加载该文件,读取使用该框架的一些核心约束条件。
该文件中的配置项及顺序如下(来自官方文档):
- configuration 配置
- properties 属性
- settings 设置
- typeAliases 类型命名
- typeHandlers 类型处理器
- objectFactory 对象工厂
- plugins 插件
- environments 环境
- environment 环境变量
- transactionManager 事务管理器
- dataSource 数据源
- environment 环境变量
- databaseIdProvider 多数据库支持(是 DML和DQL 节点的一个属性,来编写匹配不同数据库的 SQL)
- mappers 映射器
下面会介绍一下常用的配置项
properties 属性
SqlMapConfig.xml可以引用java属性文件中的配置信息如下:
在classpath下定义db.properties文件,如下:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
SqlMapConfig.xml引用如下:
<!-- 加载属性文件 -->
<properties resource="db.properties">
<!--properties中还可以配置一些属性名和属性值 -->
<!-- <property name="jdbc.driver" value=""/> -->
</properties>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理,事务控制由mybatis-->
<transactionManager type="JDBC"/>
<!-- 数据库连接池,由mybatis管理-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
注意: MyBatis 将按照下面的顺序来加载属性:
-
在 properties 元素体内定义的属性首先被读取。
-
然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。
-
最后读取parameterType(方法传递参数)传递的属性,它会覆盖已读取的同名属性。
由于mybatis框架在加载配置文件中内容的顺序为上述所述(元素体>配置文件>parameterType)因此,通过parameterType传递的属性具有最高优先级,resource或 url 加载的属性次之,最低优先级的是 properties 元素体内定义的属性。
建议:
-
不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。
-
在properties文件中定义属性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX
新版本新特性
从MyBatis 3.4.2开始,你可以为占位符指定一个默认值。例如:
<dataSource type="POOLED">
<!-- ... -->
<property name="username" value="${username:zju_user}"/> <!-- 若从以上三种方式的配置文件中均未找到username属性,那么则默认username的值为zju_user -->
</dataSource>
注意: 这个特性默认是关闭的。如果你利用上述方法为参数指定一个默认值, 你需要添加一个指定的属性来开启这个特性。需要进行如下配置:
<properties resource="db.properties">
<!-- ... -->
<property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
</properties>
上述补充:
你可以使用 “:” 作为属性键(e.g. db:username) 或者你也可以在sql定义中使用 OGNL 表达式的三元运算符(e.g. ${tableName != null ? tableName : ‘global_constants’}), 你应该通过增加一个指定的属性来改变分隔键和默认值的字符。完整配置例如:
<properties resource="db.properties">
<!-- ... -->
<property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
<property name="org.apache.ibatis.parsing.PropertyParser.default-value-separator" value="?:"/>
</properties>
<dataSource type="POOLED">
<!-- ... -->
<property name="username" value="${db:username?:zju_user}"/>
</dataSource>
databaseIdProvider多数据库支持
该标签被使用在映射文件的DML及DQL操作配置中。MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。
执行的优先级为匹配databaseId>无databaseId的约束条件。
- 在SqlMapConfig.xml文件中的配置如下:
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql" />
<property name="Oracle" value="oracle" />
</databaseIdProvider>
- 在mybatis与Spring整合的项目中需要在Spring的核心配置文件中bean.xml中的SqlSessionFactory部分配置databaseIdProvider属性。
<!--
配置 databaseIdProvider
该属性的类型为: DatabaseIdProvider 类型.
VendorDatabaseIdProvider 正是 DatabaseIdProvider 接口的一个实现类.
而 VendorDatabaseIdProvider 只有一个属性: properties,是 Properties 类型. 用于配置数据库的映射关系.
key: 数据库的名字. 是 DatabaseMetaData#getDatabaseProductName() 方法的返回值.
MySQL 的返回值为 MySQL. Oracle 的返回值为 Oracle.
val: 映射的值. 供在 Mapper.xml 文件中的 databaseId 属性使用(用法见下文案例配置)
-->
<property name="databaseIdProvider">
<bean class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">
<property name="properties">
<props>
<prop key="MySQL">mysql</prop>
<prop key="Oracle">oracle</prop>
</props>
</property>
</bean>
</property>
databaseId解释
说明:该标签表示数据库的ID,是 select、update、delete、insert 节点的一个属性。
例如:mysql的获取系统时间函数 NOW()和oracle的获取系统时间to_char(sysdate,’yyyy-mm-dd hh24:mi:ss’) 是不同的。那么我们可以针对同一个修改可以写两个update语句,他们的databaseId属性不一样。
<select id="SelectTime" resultType="String" databaseId="mysql">
SELECT NOW() FROM dual
</select>
<select id="SelectTime" resultType="String" databaseId="oracle">
SELECT 'oralce'||to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') FROM dual
</select>
settings设置
mybatis全局配置参数,全局参数将会影响mybatis的运行行为。如下:
<?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>
<!-- mybatis 的全局设置. 其中可以加入多个 setting 子节点 -->
<settings>
<!--
映射标准的列名和标准的 bean 的属性名的对应关系
标准的列名: 多个单词使用 _ 进行连接
标准的属性名: 多个单词, 从第二个单词开始, 每个单词的首字母大写.
例如 last_name 和 lastName
-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
其中具体的配置属性(name)如下【来源官方配置文件】
Setting(设置) | Description(描述) | Valid Values(验证值组) | Default(默认值) |
---|---|---|---|
cacheEnabled | 在全局范围内启用或禁用缓存配置任何映射器在此配置下。 | true|false | TRUE |
lazyLoadingEnabled | 在全局范围内启用或禁用延迟加载。禁用时,所有协会将热加载。 | true|false | TRUE |
aggressiveLazyLoading | 启用时,有延迟加载属性的对象将被完全加载后调用懒惰的任何属性。否则,每一个属性是按需加载。 | true|false | TRUE |
multipleResultSetsEnabled | 允许或不允许从一个单独的语句(需要兼容的驱动程序)要返回多个结果集。 | true|false | TRUE |
useColumnLabel | 使用列标签,而不是列名。在这方面,不同的驱动有不同的行为。参考驱动文档或测试两种方法来决定你的驱动程序的行为如何。 | true|false | TRUE |
useGeneratedKeys | 允许JDBC支持生成的密钥。兼容的驱动程序是必需的。此设置强制生成的键被使用,如果设置为true,一些驱动会不兼容性,但仍然可以工作。 | true|false | FALSE |
autoMappingBehavior | 指定MyBatis的应如何自动映射列到字段/属性。NONE自动映射。 PARTIAL只会自动映射结果没有嵌套结果映射定义里面。 FULL会自动映射的结果映射任何复杂的(包含嵌套或其他)。 | NONE, PARTIAL, FULL | PARTIAL |
defaultExecutorType | 配置默认执行人。SIMPLE执行人确实没有什么特别的。 REUSE执行器重用准备好的语句。 BATCH执行器重用语句和批处理更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置驱动程序等待一个数据库响应的秒数。 | Any positive integer | Not Set (null) |
safeRowBoundsEnabled | 允许使用嵌套的语句RowBounds。 | true|false | FALSE |
mapUnderscoreToCamelCase | 从经典的数据库列名A_COLUMN启用自动映射到骆驼标识的经典的Java属性名aColumn。 | true|false | FALSE |
localCacheScope | MyBatis的使用本地缓存,以防止循环引用,并加快反复嵌套查询。默认情况下(SESSION)会话期间执行的所有查询缓存。如果localCacheScope=STATMENT本地会话将被用于语句的执行,只是没有将数据共享之间的两个不同的调用相同的SqlSession。 | SESSION | STATEMENT | SESSION |
dbcTypeForNull | 指定为空值时,没有特定的JDBC类型的参数的JDBC类型。有些驱动需要指定列的JDBC类型,但其他像NULL,VARCHAR或OTHER的工作与通用值。 | JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER | OTHER |
lazyLoadTriggerMethods | 指定触发延迟加载的对象的方法。 | A method name list separated by commas | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定所使用的语言默认为动态SQL生成。 | A type alias or fully qualified class name. | org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver |
callSettersOnNulls | 指定如果setter方法或地图的put方法时,将调用检索到的值是null。它是有用的,当你依靠Map.keySet()或null初始化。注意原语(如整型,布尔等)不会被设置为null。 | true|false | FALSE |
logPrefix | 指定的前缀字串,MyBatis将会增加记录器的名称。 | Any String | Not set |
logImpl | 指定MyBatis的日志实现使用。如果此设置是不存在的记录的实施将自动查找。 | SLF4J | LOG4J |
proxyFactory | 指定代理工具,MyBatis将会使用创建懒加载能力的对象。 | CGLIB | JAVASSIST |
例如:
<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="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<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>
typeAliases类型命名
类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。例如:
<typeAliases>
<!-- 针对单个别名定义
type:类型的路径 alias:别名 -->
<!-- <typeAlias type="cn.itcast.mybatis.po.User" alias="user"/> -->
<!-- 批量别名定义
指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写都可以)
-->
<package name="cn.itcast.mybatis.po"/>
</typeAliases>
typeHandlers 类型处理器
无论是 MyBatis在预处理语句(PreparedStatement)中设置一个参数,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成 Java 类型。
类型处理器(typeHanflers)则用于java类型和jdbc类型映射,其中,mybatis自带的类型处理器基本上能够满足开发者在项目中的常用需求,不需要自定义类型处理器,如下所示:
<select id="findUserById" parameterType="int" resultType="user">
select * from user where id = #{id}
</select>
同时,你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler, 然后可以选择性地将它映射到一个 JDBC 类型。比如:
//java实现类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);
}
}
<!-- mybatis-config.xml核心配置文件 -->
<typeHandlers>
<typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>
使用这个的类型处理器将会覆盖已经存在的处理 Java 的 String 类型属性和 VARCHAR 参数及结果的类型处理器。 要注意 MyBatis不会窥探数据库元信息来决定使用哪种类型,所以你必须在参数和结果映射中指明那是 VARCHAR 类型的字段, 以使其能够绑定到正确的类型处理器上。 这是因为:MyBatis 直到语句被执行才清楚数据类型。
environments配置环境
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者共享相同 Schema 的多个生产数据库, 想使用相同的 SQL 映射。许多类似的用例。
注意:尽管可以配置多个环境,每个 SqlSessionFactory 实例只能选择其一。
对于指定使用哪个数据库实例,可以将换环境作为参数传递给SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
<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”)。
事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type=”[JDBC|MANAGED]”):
- JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
- MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JavaEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。例如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
_提示:如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器, 因为 Spring 模块会使用自带的管理器来覆盖前面的配置。
数据源
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
许多 MyBatis 的应用程序会按示例中的例子来配置数据源。虽然这是可选的,但为了使用延迟加载,数据源是必须配置的。
有三种内建的数据源类型(也就是type=”[UNPOOLED|POOLED|JNDI]”)。
- UNPOOLED– 这个数据源的实现只是每次被请求时打开和关闭连接。虽然有点慢,但对于在数据库连接可用性方面没有太高要求的简单应用程序来说,是一个很好的选择。 不同的数据库在性能方面的表现也是不一样的,对于某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。
- POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这是一种使得并发 Web 应用快速响应请求的流行处理方式。
- JNDI – 这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
mappers映射器
Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。一共有四种方法配置映射文件的资源路径。
1、使用相对于类路径的资源
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="sqlmap/User.xml"/>
</mappers>
2、使用完全限定路径
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/project/config/sqlmap/User.xml"/>
</mappers>
<!--windows系统下 -->
<mapper url="file:///D:\workspace\project\config\sqlmap\User.xml" />
3、使用mapper接口类路径
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="edu.zju.cst.mapper.UserMapper"/>
</mappers>
4、注册指定包下的所有mapper接口(常用)
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="edu.zju.cst.mapper"/>
</mappers>
说明:该方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。