MyBatis实战之配置
MyBatis最重要的配置也就两个,一个是mybatis-config.xml,又称MyBatis的全局配置,另一个就是XXXDao.xml或XXXMapper.xml映射配置。
mybatis-config.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> <typeAliases> <package name="com.blog.entity"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/blog_test"/> <property name="username" value="root"/> <property name="password" value="1234"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mybatis/mapping/UserDao.xml"/> </mappers> </configuration>
1.properties元素
properties是一个配置属性的元素,让我们能在配置文件的上下文使用它。
MyBatis提供3种配置方式。
(1)properties子元素(如上述);
(2)properties配置文件(例如读取jdbc.properties配置文件,这个在spring-mybatis整合得以体现);
(3)程序参数传递(本质上是读取properties配置文件,通过键值对的读取并传递参数);
关于它们的优先级
首先,properties元素体内指定的属性首先被读取;
其次,根据properties元素中的resource属性读取类路径下属性文件,或者根据url属性指定的路径读取属性文件,并覆盖已读取的同名属性;
最后,读取作为方法参数传递的属性,并覆盖已读取的同名属性;
因此,通过方法参数传递的属性具有最高优先级,resource/url属性中指定的配置文件次之,最低优先级的是properties属性中指定的属性。因此,实际操作中我们需要注意以下三点:
(1)不要使用混合的方式,这样会使得管理混乱;
(2)首先方式是使用properties文件;
(3)如果我们需要对其进行加密或者其他加工以满足特殊的要求,不妨按照程序参数传递方式;
2.设置
设置(settings)在MyBatis中是最复杂的配置,同时也是最为重要的配置内容之一,它会改变MyBatis运行时的行为。即使不配置settings,MyBatis也可以正常的工作,不过了解settings的配置内容,以及它们的作用仍然十分必要。
Settings的配置内容如下图所示:
图一:
图二:
图三:
图四:
图五:
图六:
配置一般情况下不需要修改太多,只仅仅修改少量就行。
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="25000" /> <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" />
3.别名
MyBatis系统定义了一些经常使用的类型的别名,例如,数值、字符串、日期和集合等,我们可以在MyBatis中直接使用它们,在使用时不要重复定义把它们给覆盖了。
让我们看看MyBatis已经定义好的别名(支持数组类型的只要加"[]" 即可使用,比如Date数组别名可以用date[]代替)。
系统定义的typeAliases 如图所示:
图一:
图二:
图三:
我们在MyBatis实战之初步 说到过别名和它的三种配置方式,所以此处不再赘述。
4.typeHandler类型处理器
MyBatis在预处理语句(PreparedStatement)中设置一个参数时,或者从结果集(ResultSet)中取出一个值,都会用注册了的typeHandler进行处理。
由于数据库可能来自不同厂商,不同的厂商设置的参数可能存在差异,同时数据库也可以自定义数据类型,typeHandler允许根据项目的需要自定义设置Java传递到数据库的参数中,或者从数据库读出数据,我们也需要进行特殊的处理,这些都可以在定义的typeHandler中处理,尤其在使用枚举的时候我们常常需要使用typeHandler进行转换。
typeHandler和别名一样,分为MyBatis系统定义和用户自定义两种。一般来说,使用MyBatis系统定义就可以实现大部分的功能,如果使用用户自定义的typeHandler,我们在处理的时候务必小心谨慎,以避免出现不必要的错误。
typeHandler 常用的配置为Java类型(javaType)、JDBC类型(jdbcType)。typeHandler的作用就是将参数从javaType转化为jdbcType,或者从数据库取出结果时把jdbcType转化为javaType。
系统注册的typeHandle简介,如下图所示:
图一:
图二:
需要注意以下几点?
(1)数值类型的精度,数据库Int、double、decimal这些类型和Java的精度、长度都是不一样的;
(2)时间精度,取数据到日用DateOnlyTypeHandler即可,用到精度为秒的用SqlTimestamp、TypeHandler等;
让我们选取一个MyBatis系统自定义的typeHandler,并了解它的具体内容。我们可以看到MyBatis源码包org.apache.ibatis.type下面定义的StringTypeHandler。StringTypeHandler是一个常用的typeHandler,负责处理String类型。
StringTypeHandler源码如下:
* Copyright 2009-2015 the original author or authors. package org.apache.ibatis.type; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; /** * @author Clinton Begin */ public class StringTypeHandler 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); } }
说明一下上面的代码:
StringTypeHandler继承BaseTypeHandler,而BaseTypeHandler实现接口typeHandler,并且自己定义了4个抽象的方法。所以继承它的时候,正如本例一样,正如本例一样需要实现其定义的4个抽象方法,这些方法已经在StringTypeHandler中用@Override注解注明了。
setParameter是PreparedStatement对象设置参数,它允许我们自己填写变换规则。
getResult则分为ResultSet用列名(columnName)或者使用列下标(columnIndex)来获取结果数据。其中还包括了用CallableStatement(存储过程)获取结果及数据的方法。
如果你想自定义Handler,除了编写一个Java类之外,还需要在mybatis-config.xml配置如下内容:
<typeHandlers> <typeHandler handler="com.blog.typehandler.MyStringHandler" javaType="string" jdbcType="varchar"/> </typeHandlers>
5.ObjectFactory
当MyBatis在构建一个结果返回的时候,都会使用ObjectFactory(对象工厂)去构建POJO,在MyBatis中可以定制自己的对象工厂。一般来说我们使用默认的ObjectFactory即可,MyBatis中默认的ObjectFactory是由org.apache.ibatis.reflection.factory.DefaultObjectFactory来提供的。在大部分的场景下我们都不用修改,如果要定制特定的工厂则需要进行配置。
例如我们自定义个ObjectFactory就需要在mybatis-config.xml配置如下内容:
<objectFactory type="com.blog.custom.MyObjectFactory"> <property name="userName" value="MyObjectFacotry"/> </objectFactory>
6.插件
插件是比较复杂的,使用时要特别小心。使用插件将覆盖一些MyBatis内部核心对象的行为,在没有了解MyBatiss内部运行原理之前我们没有必要去讨论它,后面会说的。
7.environment配置环境
配置环境可以注册多个数据源,每个数据源分为两大部分,一个是数据库源的配置,另一个是数据库事务的配置。
数据源配置如下:
<environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/blog_test"/> <property name="username" value="root"/> <property name="password" value="1234"/> </dataSource> </environment> </environments>
分析下上述配置:
(1)environments中的属性default,标明在缺省的情况下,我们将启动哪个数据源配置;
(2)environment元素是配置一个数据源的开始,属性id是设置这个数据源的标志,以便MyBatis上下文使用它;
(3)transactionManager配置的数据库事务,其中type属性有三种配置方式:
a.JDBC,采用JDBC方式管理事务,在独立编码中我们常常使用;
b.MANAGED,采用容器方式管理事务,在JNDI数据源中常用;
c.自定义,由使用者自定义数据库事务管理办法,适用于特殊应用。
(4)property元素则是可以配置数据源的各类属性,假如在此配置autoCommit=false,则是要求数据源不自动提交,默认情况是自动提交;
(5)dataSource标签,是配置数据源连接的信息,type属性是提供我们对数据库连接方式的配置,同样MyBatis提供了这么几种配置方式:
a.UNPOOLED,非连接池数据库;
b.POOLED,连接池数据库;
c.JNDI,JNDI数据源;
d.自定义数据源;
其中,配置的property元素,就是定义数据库的各类参数。
关于数据库事务MyBatis,它是由SqlSession去控制的,我们通过SqlSession提交或者回滚。我们插入一个角色对象,如果成功就提交,否则就回滚。不过大部分情况都是由Spring框架去控制。后面会讲到。
MyBatis内部为我们提供三种数据源的实现方式:
(1)UNPOOLED,非连接池,使用MyBatis提供的org.apache.ibatis.datasource.unpooled.UnpooledDataSource实现;
(2)POOLED,连接池,使用MyBatis提供的org.apache.ibatis.datasource.pooled.PooledDataSource实现;
(3)JNDI,使用MyBatis提供的org.apache.ibatis.datasource.jndi.JndiDataSourceFactory来获取数据源;
我们只需把数据源的属性type定义为UNPOOLED、POOLED、JNDI即可。
9.databaseIdProvider 数据库厂商标识
在相同数据库厂商的环境下,数据库厂商标识没有什么意义,在实际的应用中使用得比较少,因为使用不同厂商数据库的系统还是比较少的。MyBatis可能会运行在不同厂商的数据库中,它为此提供一个数据库标识,并提供自定义,它的作用在于指定SQL到对应的数据库厂商提供的数据库中运行。
这个不是特别重要,在此不详说,告诉读者有个这玩意。
主要参考《深入浅出MyBatis原理和实战》