在上次的Mybatis使用当中有两个.xml文件的使用,一个是mybatis的配置文件,另一个则是Mapper接口的映射器实例。就此详细和更进一步地对Mybatis的配置文件进行Py。MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置(settings)和属性(properties)信息。文档的顶层结构如下:
configuration 配置
- properties 属性
- settings 设置
- typeAliases 类型别名
- typeHandlers 类型处理器
- objectFactory 对象工厂
- plugins 插件
- environments 环境
- environment 环境变量
- transactionManager 事务管理器
- dataSource 数据源
- databaseIdProvider 数据库厂商标识
- mappers 映射器
Properties属性
属性配置元素Properties可以将配置值写入xml当中(像上次直接写到对应变量后其也很简单,但是当config.xml达到一定规模就有点恐怖了。)当然也可以写到properties文件当中,使用属性文件的key作为占位符,在DataSource的property子元素value属性中可以使用${key}表达式来取值。现将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> <properties resource="db.properties"> <!-- 这里优先properties文件。不受干扰 --> <property name="jdbc.username" value="stringair"/> <property name="jdbc.userpassword" value="stringair"/> </properties> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <!-- <property name="driver" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:xe" /> <property name="username" value="xin" /> <property name="password" value="root" /> --> </dataSource> </environment> </environments> <mappers> <mapper resource="xin/work/studentMapper.xml" /> </mappers> </configuration>
Setting设置
即全局元素的参数设置,可以覆盖Mybatis默认的一些全局参数设置-=:
<settings> <!-- 这个配置使全局的映射器启用或禁用缓存 --> <setting name="cacheEnabled" value="true" /> <!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载 --> <setting name="lazyLoadingEnabled" value="true" /> <!-- 允许或不允许多种结果集从一个单独的语句中返回(需要适合的驱动) --> <setting name="multipleResultSetsEnabled" value="true" /> <!-- 使用列标签代替列名。不同的驱动在这方便表现不同。参考驱动文档或充分测试两种方法来决定所使用的驱动 --> <setting name="useColumnLabel" value="true" /> <!-- 允许JDBC支持生成的键。需要适合的驱动。 --> <setting name="useGeneratedKeys" value="false" /> <!-- 指定MyBatis如何自动映射列到字段/属性。PARTIAL只会自动映射简单、没有嵌套的结果。FULL会自动映射任意复杂的结果(嵌套的或其他情况) --> <setting name="autoMappingBehavior" value="PARTIAL" /> <!-- 配置默认的执行器。SIMPLE执行器没有什么特别之处。REUSE执行器重用预处理语句。BATCH执行器重用语句和批量更新 --> <setting name="defaultExecutorType" value="SIMPLE" /> <!-- 设置超时时间,它决定驱动等待一个数据库响应的时间 --> <setting name="defaultStatementTimeout" value="25000" /> <!-- 允许在嵌套语句中使用分页(RowBounds)默认false --> <setting name="safeRowBoundsEnabled" value="false" /> <!-- 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。默认false --> <setting name="mapUnderscoreToCamelCase" value="false" /> <!-- MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 --> <setting name="localCacheScope" value="SESSION" /> <!-- 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 --> <setting name="jdbcTypeForNull" value="OTHER" /> <!-- 指定对象的哪个方法触发一次延迟加载。 --> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode ,toString" /> <!-- CGLIB | JAVASSIST 默认JAVASSIST(MyBatis 3.3 or above) --> <!-- 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 --> <setting name="proxyFactory" value="JAVASSIST" /> <!-- 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载。 --> <setting name="aggressiveLazyLoading" value="true" /> <!-- 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 --> <setting name="logImpl" value="LOG4J " /> <!-- 指定 MyBatis 增加到日志名称的前缀。值可以是任意字符串 --> <setting name="logPrefix" value="LOG4J " /> <!-- 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。 默认false --> <setting name="callSettersOnNulls" value="false " /> </settings>
当然详细的设置可不是这么点。更多详细请戳Mybatis的官方文档,会有更加详细的介绍。
typeAlias:类型别名
当我使用例如上次的那样来写配置文件的时候,我返回的一些值为对象,所以我的返回格式便是包名+类名。其长度大且复杂,所以typeAlias可以让你拥有一次重新取名字的机会(美滋滋)。譬如:
<type Aliases> <type Alias alias="Student" type="xin.work.Student" /> </type Aliases> <!-- --> <insert id="insertStudent" parameterType="Student"> insert into books(id,name,age) values(#{id},#{name},#{age}) </insert> <select id="selectStudent" resultType="Student"> select id,name,age from t_student where id = #{id} </select>
typeHandlers元素: 类型处理器
其实在处理数据的时候大多都是经过TypeHandler的类的处理的,当然在你没有定义的时候则是自行处理,所以当你出现自定义的类亦或者数据类型时默认的家伙可就不认识你的类型了,所以在这个时候往往通过继承BaseTypeHandler<T>。所以就先定义一个类类型的:
package xin.work; public class Adress { private String country; private String city; public Adress() { } public Adress(String country, String city) { super(); this.country = country; this.city = city; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Override public String toString() { return "Adress [country=" + country + ", city=" + city + "]"; } }
在创建好此类之后将Student类下也添加Adress类的参数,完成之后写TypeHandlers实现TypeHandler接口。
package xin.Handler; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeHandler; import xin.work.Adress; public class AdressHandler implements TypeHandler<Adress> { @Override public Adress getResult(ResultSet arg0, String arg1) throws SQLException { // TODO Auto-generated method stub String result = arg0.getString(arg1); return getAdress(result); } @Override public Adress getResult(ResultSet arg0, int arg1) throws SQLException { // TODO Auto-generated method stub String result = arg0.getString(arg1); return getAdress(result); } private Adress getAdress(String result) { String info[] = result.split(","); if (info.length == 2) { Adress adrs = new Adress(info[0], info[1]); return adrs; } return null; } @Override public Adress getResult(CallableStatement arg0, int arg1) throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setParameter(PreparedStatement arg0, int arg1, Adress arg2, JdbcType arg3) throws SQLException { // TODO Auto-generated method stub System.out.println(arg2); String adress = arg2.getCountry() + "," + arg2.getCity(); arg0.setString(arg1, adress); } }
在config.xml 文件中填入配置信息:
<typeHandlers> <typeHandler handler="xin.Handler.AdressHandler" jdbcType="VARCHAR" javaType="xin.work.Adress" /> </typeHandlers>
对学生类稍作修改便可以发现这个的强势。
environment
MyBatis支持配置多个dataSource环境,可以将应用部署到不同的环境上,如DEV(开发环境),TEST(测试换将),QA(质量评估环境),UAT(用户验收环境),PRODUCTION(生产环境),可以通过将默认environments值设置成想要的environment的id值。有时候,我们可能需要在相同的应用下使用多个数据库,比如我们可能有SHOPPING-CART数据库来存储所有的订单明细;使用REPORTS数据库存储订单明细的合计,用作报告。(也就是如果系统在运行期间如果有切换数据库环境的需求,mybatis中也可以很轻松的实现).
1.environments中的default属性,标明在缺省的情况下,我们将启用那个数据源的配置
2.environment:environment用来配置一个数据源
2.1 id属性:定义数据源的标识,以方便mybatis在上下文中使用
2.2 transactionManager 标签:事务管理器
2.2.1 type:MyBatis支持的事务管理类型
mybatis支持的事务管理类型有:JDBC 、 MANAGED
JDBC事务管理器的使用,是在【jdbc程序】负责管理数据库连接的生命周期(提交、回退等等)的时候。如果将TransactionManager 属性设置成JDBC,MyBatis内部将使用JdbcTransactionFactory类创建TransactionManager。在独立编码中常用。 MANAGED事务管理器的使用,是在【应用服务器】负责管理数据库连接生命周期的时候。如果将TransactionManager属性设置成MANAGED时,MyBatis内部使用ManagedTransactionFactory 类创建事务管理器TransactionManager。例如,当一个Java EE的应用程序部署在类似JBoss,WebLogic,GlassFish应用服务器上时,它们会使用EJB进行应用服务器的事务管理能力。在这些管理环境中,你可以使用MANAGED事务管理器。
注:Managed 是托管的意思,即我们编写的应用程序本身不去管理事务,而是把事务管理交给应用所在的服务器进行管理。
2.3 dataSource 标签
dataSource表示的是数据源:至少会包括该连接数据库的各种信息
<dataSource type="POOLED"> <property name="driver" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource>
mappers元素: SQL映射
SQLMapper文件中包含的SQL映射语句将会被应用通过使用其标签中的id值来执行。我们需要在mybatis-config.xml文件中配置SQLMapper文件的位置。
<mappers> <mapper resource="xin/work/studentMapper.xml" /> </mappers>