转:MyBatis常用配置(1)
MyBatis是什么?
在移动互联网时代,MyBatis 成为了目前互联网 Java 持久框架的首选。
Mybatis本是 Apache 的一个开源项目——iBatis,2010 年这个项目由 Apache Software Foundation 迁移到了 Google Code,并且改名为 MyBatis。
MyBatis 是一个基于 Java 的持久层框架。MyBatis 提供的持久层框架包括 SQL Maps 和 Data Access Objects(DAO),它消除了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。
MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java 对象)映射成数据库中的记录。
目前,Java 的持久层框架产品有许多,常见的有 Hibernate 和 MyBatis。总的来说,MyBatis 是一个小巧、方便、高效、简单、直接、半自动化的持久层框架,Hibernate 是一个强大、方便、高效、复杂、间接、全自动化的持久层框架。所以对于性能要求不太苛刻的系统,比如管理系统、ERP 等推荐使用 Hibernate,而对于性能要求高、响应快、灵活的系统则推荐使用 MyBatis。
MyBatis配置文件
MyBatis 配置文件并不复杂,它所有的元素如下所示。
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 3 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 4 <configuration><!-- 配置 --> 5 <properties /><!-- 属性 --> 6 <settings /><!-- 设置 --> 7 <typeAliases /><!-- 类型命名 --> 8 <typeHandlers /><!-- 类型处理器 --> 9 <objectFactory /><!-- 对象工厂 --> 10 <plugins /><!-- 插件 --> 11 <environments><!-- 配置环境 --> 12 <environment><!-- 环境变量 --> 13 <transactionManager /><!-- 事务管理器 --> 14 <dataSource /><!-- 数据源 --> 15 </environment> 16 </environments> 17 <databaseIdProvider /><!-- 数据库厂商标识 --> 18 <mappers /><!-- 映射器 --> 19 </configuration>
其中 properties、settings、typeAliases、typeHandler、plugin、environments、mappers 是常用的内容。需要注意的是,MyBatis 配置项的顺序不能颠倒。如果颠倒了它们的顺序,那么在 MyBatis 启动阶段就会发生异常,导致程序无法运行。
1. properties
properties 属性可以给系统配置一些运行参数,可以放在 XML 文件或者 properties 文件中,而不是放在 Java 编码中,这样的好处在于方便参数修改,而不会引起代码的重新编译。一般而言,MyBatis 提供了 3 种方式让我们使用 properties:property子元素、properties文件、程序代码传递
- property 子元素
以下面代码为基础,使用 property 子元素将数据库连接的相关配置进行改写,如下所示。
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 3 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 4 <configuration> 5 <properties> 6 <property name="driver" value="com.mysql.jdbc.Driver" /> 7 <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8" /> 8 <property name="username" value="root" /> 9 <property name="password" value="1128" /> 10 </properties> 11 <typeAliases> 12 <typeAlias alias="role" type="com.mybatis.po.Role"/> 13 </typeAliases> 14 <!--数据库环境--> 15 <environments default="development"> 16 <environment id="development"> 17 <transactionManager type="JDBC" /> 18 <dataSource type="POOLED"> 19 <property name="driver" value="com.mysql.jdbc.Driver" /> 20 <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8" /> 21 <property name="username" value="root" /> 22 <property name="password" value="1128" /> 23 </dataSource> 24 </environment> 25 </environments> 26 <!-- 映射文件 --> 27 <mappers> 28 <mapper resource="com/mybatis/mapper/RoleMapper.xml" /> 29 </mappers> 30 </configuration>
这里使用了元素 <properties> 下的子元素 <property> 定义,用字符串 database.username 定义数据库用户名,然后就可以在数据库定义中引入这个已经定义好的属性参数,如 ${database.username},这样定义一次就可以到处引用了。但是如果属性参数有成百上千个,显然使用这样的方式不是一个很好的选择,这个时候可以使用 properties 文件。
- properties 文件
使用 properties 文件是比较普遍的方法,一方面这个文件十分简单,其逻辑就是键值对应,我们可以配置多个键值放在一个 properties 文件中,也可以把多个键值放到多个 properties 文件中,这些都是允许的,它方便日后维护和修改。
这里创建一个jdbc.properties如下所示:
database.driver=com.mysql.jdbc.Driver database.url=jdbc:mysql://localhost:3306/mybatis database.username=root database.password=1128
在MyBatis中通过<properties>的属性resource来引入properties文件。
<properties resource="jdbc.properties"/>
也可以按 ${database.username} 的方法引入 properties 文件的属性参数到 MyBatis 配置文件中。这个时候通过维护 properties 文件就可以维护我们的配置内容了。
- 程序代码传递
在真实的生产环境中,数据库的用户密码是对开发人员和其他人员保密的。运维人员为了保密,一般都需要把用户和密码经过加密成为密文后,配置到 properties 文件中。对于开发人员及其他人员而言,就不知道其真实的用户密码了,数据库也不可能使用已经加密的字符串去连接,此时往往需要通过解密才能得到真实的用户和密码了。
现在假设系统已经为提供了这样的一个 CodeUtils.decode(str)进行解密,那么我们在创建 SqlSessionFactory 前,就需要把用户名和密码解密,然后把解密后的字符串重置到 properties 属性中,如下所示。
1 String resource = "mybatis-config.xml"; 2 InputStream inputStream; 3 Inputstream in = Resources.getResourceAsStream("jdbc.properties"); 4 Properties props = new Properties(); 5 props.load(in); 6 String username = props.getProperty("database.username"); 7 String password = props.getProperty("database.password"); 8 //解密用户和密码,并在属性中重置 9 props.put("database.username", CodeUtils.decode(username)); 10 props.put ("database.password", CodeUtils.decode(password)); 11 inputstream = Resources.getResourceAsStream(resource); 12 //使用程序传递的方式覆盖原有的properties属性参数 13 SqlSessionFactory = new SqlSessionFactoryBuilder().build(inputstream, props);
首先使用 Resources 对象读取了一个 jdbc.properties 配置文件,然后获取了它原来配置的用户和密码,进行解密并重置,最后使用 SqlSessionFactoryBuilder 的 build 方法,传递多个 properties 参数来完成。这将覆盖之前配置的密文,这样就能连接数据库了,同时也满足了运维人员对数据库用户和密码安全的要求。
2. settings
在 MyBatis 中 settings 是最复杂的配置,它能深刻影响 MyBatis 底层的运行,但是在大部分情况下使用默认值便可以运行,所以在大部分情况下不需要大量配置它,只需要修改一些常用的规则即可,比如自动映射、驼峰命名映射、级联规则、是否启动缓存、执行器(Executor)类型等。settings 配置项说明,如下表所示。
| 配置项 | 作用 | 配置选项 | 默认值 |
|---|---|---|---|
| cacheEnabled | 该配置影响所有映射器中配置缓存的全局开关 | true|false | true |
| lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。在特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态 | true|false | false |
| aggressiveLazyLoading | 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载 | true|felse | 版本3.4.1 (不包含) 之前 true,之后 false |
| multipleResultSetsEnabled | 是否允许单一语句返回多结果集(需要兼容驱动) | true|false | true |
| useColumnLabel | 使用列标签代替列名。不同的驱动会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果 | true|false | true |
| useGeneratedKeys | 允许JDBC 支持自动生成主键,需要驱动兼容。如果设置为 true,则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby) | true|false | false |
| autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射。 PARTIAL 表示只会自动映射,没有定义嵌套结果集和映射结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套) |
NONE、PARTIAL、FULL | PARTIAL |
| autoMappingUnkno wnColumnBehavior | 指定自动映射当中未知列(或未知属性类型)时的行为。 默认是不处理,只有当日志级别达到 WARN 级别或者以下,才会显示相关日志,如果处理失败会抛出 SqlSessionException 异常 | NONE、WARNING、FAILING | NONE |
| defaultExecutorType | 配置默认的执行器。SIMPLE 是普通的执行器;REUSE 会重用预处理语句(prepared statements);BATCH 执行器将重用语句并执行批量更新 | SIMPLE、REUSE、BATCH | SIMPLE |
| defaultStatementTimeout | 设置超时时间,它决定驱动等待数据库响应的秒数 | 任何正整数 | Not Set (null) |
| defaultFetchSize | 设置数据库驱动程序默认返回的条数限制,此参数可以重新设置 | 任何正整数 | Not Set (null) |
| safeRowBoundsEnabled | 允许在嵌套语句中使用分页(RowBounds)。如果允许,设置 false | true|false | false |
| safeResultHandlerEnabled | 允许在嵌套语句中使用分页(ResultHandler)。如果允许,设置false | true|false | true |
| mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射 | true|false | false |
| localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速联复嵌套査询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlScssion 的不同调用将不会共享数据 |
SESSION|STATEMENT | SESSION |
| jdbcTypeForNull | 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER | NULL、VARCHAR、OTHER | OTHER |
| lazyLoadTriggerMethods | 指定哪个对象的方法触发一次延迟加载 | — | equals、clone、hashCode、toString |
| defaultScriptingLanguage | 指定动态 SQL 生成的默认语言 | — | org.apache.ibatis .script.ing.xmltags .XMLDynamicLanguageDriver |
| callSettersOnNulls | 指定当结果集中值为 null 时,是否调用映射对象的 setter(map 对象时为 put)方法,这对于 Map.kcySet() 依赖或 null 值初始化时是有用的。注意,基本类型(int、boolean 等)不能设置成 null | true|false | false |
| logPrefix | 指定 MyBatis 增加到日志名称的前缀 | 任何字符串 | Not set |
| loglmpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动査找 | SLF4J|LOG4J|LOG4J2|JDK_LOGGING |COMMONS_LOGGING |ST DOUT_LOGGING|NO_LOGGING |
Not set |
| proxyFactory | 指定 MyBatis 创建具有延迟加栽能力的对象所用到的代理工具 | CGLIB|JAVASSIST | JAVASSIST (MyBatis 版本为 3.3 及以上的) |
| vfsImpl | 指定 VFS 的实现类 | 提供 VFS 类的全限定名,如果存在多个,可以使用逗号分隔 | Not set |
| useActualParamName | 允许用方法参数中声明的实际名称引用参数。要使用此功能,项目必须被编译为 Java 8 参数的选择。(从版本 3.4.1 开始可以使用) | true|false | true |
settings 的配置项很多,但是真正用到的不会太多,我们把常用的配置项研究清楚就可以了,比如关于缓存的 cacheEnabled,关于级联的 lazyLoadingEnabled 和 aggressiveLazy Loading,关于自动映射的 autoMappingBehavior 和 mapUnderscoreToCamelCase,关于执行器类型的 defaultExecutorType 等。
这里给出一个全量的配置样例,如下所示:
1 <settings> 2 <setting name="cacheEnabled" value="true"/> 3 <setting name="lazyLoadingEnabled" value="true"/> 4 <setting name="multipleResultSetsEnabled" value="true"/> 5 <setting name="useColumnLabel" value="true"/> 6 <setting name="useGeneratedKeys" value="false"/> 7 <setting name="autoMappingBehavior" value="PARTIAL"/> 8 <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/> 9 <setting name="defaultExecutorType" value="SIMPLE"/> 10 <setting name="defaultStatementTimeout" value="25"/> 11 <setting name="defaultFetchSize" value="100"/> 12 <setting name="safeRowBoundsEnabled" value="false"/> 13 <setting name="mapUnderscoreToCamelCase" value="false"/> 14 <setting name="localCacheScope" value="SESSION"/> 15 <setting name="jdbcTypeForNull" value="OTHER"/> 16 <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> 17 </settings>
3. TypeAliases
由于类的全限定名称很长,需要大量使用的时候,总写那么长的名称不方便。在 MyBatis 中允许定义一个简写来代表这个类,这就是别名,别名分为系统定义别名和自定义别名。
在 MyBatis 中别名由类 TypeAliasRegistry(org.apache.ibatis.type.TypeAliasRegistry)去定义。注意,在 MyBatis 中别名不区分大小写。
系统定义别名
自定义别名
由于现实中,特别是大型互联网系统中存在许多对象,比如用户(User)这个对象有时候需要大量重复地使用,因此 MyBatis 也提供了用户自定义别名的规则。我们可以通过 TypeAliasRegistry 类的 registerAlias 方法注册,也可以采用配置文件或者扫描方式来自定义它。
使用配置文件定义:
<typeAliases><!--别名-->
<typeAlias alias="role" type="com.mybatis.po.Role"/>
<typeAlias alias="role" type="com.mybatis.po.User"/>
</typeAliases>
这样就可以定义一个别名了。如果有很多类需要定义别名,那么用这样的方式进行配置可就不那么轻松了。MyBatis 还支持扫描别名。比如上面的两个类都在包 com.mybatis.po 之下,那么就可以定义为:
<typeAliases><!--别名-->
<package name="com.mybatis.po"/>
</typeAliases>
这样 MyBatis 将扫描这个包里面的类,将其第一个字母变为小写作为其别名,比如类 Role 的别名会变为 role,而 User 的别名会变为 user。使用这样的规则,有时候会出现重名。
比如 com.mybatis.po.User 这个类,MyBatis 还增加了对包 com.mybatis.po 的扫描,那么就会出现异常,这个时候可以使用 MyBatis 提供的注解 @Alias("user3")进行区分,如下所示。
package com.mybatis.po; @Alias("user3") public Class User { ...... }
这样就能够避免因为别名重名导致的扫描失败的问题。
4. typeHandler
在 JDBC 中,需要在 PreparedStatement 对象中设置那些已经预编译过的 SQL 语句的参数。执行 SQL 后,会通过 ResultSet 对象获取得到数据库的数据,而这些 MyBatis 是根据数据的类型通过 typeHandler 来实现的。
在 typeHandler 中,分为 jdbcType 和 javaType,其中 jdbcType 用于定义数据库类型,而 javaType 用于定义 Java 类型,那么 typeHandler 的作用就是承担 jdbcType 和 javaType 之间的相互转换。如下图所示。

在很多情况下我们并不需要去配置 typeHandler、jdbcType、javaType,因为 MyBatis 会探测应该使用什么类型的 typeHandler 进行处理,但是有些场景无法探测到。对于那些需要使用自定义枚举的场景,或者数据库使用特殊数据类型的场景,可以使用自定义的 typeHandler 去处理类型之间的转换问题。
和别名一样,在 MyBatis 中存在系统定义 typeHandler 和自定义 typeHandler。MyBatis 会根据 javaType 和数据库的 jdbcType 来决定采用哪个 typeHandler 处理这些转换规则。系统提供的 typeHandler 能覆盖大部分场景的要求,但是有些情况下是不够的,比如我们有特殊的转换规则,枚举类就是这样。
5. environments
在 MyBatis 中,运行环境主要的作用是配置数据库信息,它可以配置多个数据库,一般而言只需要配置其中的一个就可以了。它下面又分为两个可配置的元素:事务管理器(transactionManager)、数据源(dataSource)。在实际的工作中,大部分情况下会采用 Spring 对数据源和数据库的事务进行管理。
运行环境配置,代码如下所示:
1 <environments default="development"> 2 <environment id="development"> 3 <transactionManager type="JDBC" /> 4 <dataSource type="POOLED"> 5 <property name="driver" value="${database.driver}" /> 6 <property name="url" 7 value="${database.url}" /> 8 <property name="username" value="${database.username}" /> 9 <property name="password" value="${database.password}" /> 10 </dataSource> 11 </environment> 12 </environments>
6. mappers
告诉MyBatis去哪里找映射文件
<configuration>
<mappers>
<mapper resource="com/mybatis/UserMapper.xml" />
</mappers>
</configuration>
MyBatis与Spring整合
导入相关JAR包
MyBatis 框架所需的 JAR 包、Spring 框架所需的 JAR 包、MyBatis 与 Spring 整合的中间 JAR 包、数据库驱动 JAR 包、数据源所需的 JAR 包。
在Spring中配置MyBatis工厂
通过与 Spring 的整合,MyBatis 的 SessionFactory 交由 Spring 来构建,在构建时需要在 Spring 的配置文件中添加如下代码:
1 <!--配置数据源--> 2 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 3 <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 4 <property name="url" value="jdbc:mysql://127.0.0.1:3306/springtest?seUnicode=true&characterEncoding=utf-8" /> 5 <property name="username" value="root" /> 6 <property name="password" value="1128" /> 7 <!-- 最大连接数 --> 8 <property name="maxTotal" value="30"/> 9 <!-- 最大空闲连接数 --> 10 <property name="maxIdle" value="10"/> 11 <!-- 初始化连接数 --> 12 <property name="initialSize" value="5"/> 13 </bean> 14 <!-- 配置SqlSessionFactoryBean --> 15 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 16 <!-- 引用数据源组件 --> 17 <property name="dataSource" ref="dataSource" /> 18 <!-- 引用MyBatis配置文件中的配置 --> 19 <property name="configLocation" value="classpath:mybatis-config.xml" /> 20 </bean>
使用Spring管理MyBatis的数据操作接口
使用 Spring 管理 MyBatis 数据操作接口的方式有多种,其中最常用、最简洁的一种是基于 MapperScannerConfigurer 的整合。该方式需要在 Spring 的配置文件中加入以下内容:
<!-- Mapper代理开发,使用Spring自动扫描MyBatis的接口并装配 (Sprinh将指定包中的所有被@Mapper注解标注的接口自动装配为MyBatis的映射接口) -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- mybatis-spring组件的扫描器,com.dao只需要接口(接口方法与SQL映射文件中的相同) -->
<property name="basePackage" value="com.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
整合实例的步骤:
1)创建应用并导入相关 JAR 包
2)创建持久化类
3)创建 SQL 映射文件(UserMapper.xml)和 MyBatis 核心配置文件(mybatis-config.xml)
4)创建数据访问接口(UserMapper)
5)创建日志文件(?)
6)创建控制层(UserController类)
7)创建 Spring 的配置文件( applicationContext.xml)
8)创建测试类(TestController)
via: http://c.biancheng.net/view/4302.html