配置顶层结构目录
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:注意:这些元素在mybatis的xml配置文件中,顺序是不可以颠倒的,否则无法构建SqlSessionFactoryBuilder实例,也就无法构建SqlSessionFactory工厂实例,更无法构建SqlSession操作数据库命令SQL对象实例。
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
1、properties(属性)
这些属性都是可外部配置且可动态替换的,既可以在典型的Java属性文件中配置,亦可通过properties元素的子元素来传递。
<properties resource="jdbc.properties">
</properties>
其中,jdbc.properties文件配置如下:注意:mybatis只是数据库库名,与mybatis无关
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456
用到的属性就可以在整个配置文件中使用来替换需要动态配置的属性值。
<?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配置文件 -->
<properties resource="jdbc.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<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>
<mappers>
<!-- 注册UserMapper.xml文件,UserMapper.xml位于com.lanhuigu.mybatis.mapper这个包下,
所以resource写成com/lanhuigu/mybatis/mapper/UserMapper.xml-->
<!--<mapper resource="com/lanhuigu/mybatis/mapper/UserMapper.xml"></mapper>-->
<package name="com.lanhuigu.mybatis.mapper"/>
</mappers>
</configuration>
其中dataSource中driver,url,username,password的value值均从配置文件jdbc.properties中通过${ }获取,从而增加程序配置的灵活性。对于properties进行如下探究。
实验1:
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="123456"/>
将jdbc.properties修改成如下,也就是将用户名和密码通过#号注释掉:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
#jdbc.username=root
#jdbc.password=123456
mybatis-config.xml中的properties配置修改为:
<?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配置文件 -->
<properties resource="jdbc.properties">
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="123456"/>
</properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<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>
<mappers>
<!-- 注册UserMapper.xml文件,UserMapper.xml位于com.lanhuigu.mybatis.mapper这个包下,
所以resource写成com/lanhuigu/mybatis/mapper/UserMapper.xml-->
<!--<mapper resource="com/lanhuigu/mybatis/mapper/UserMapper.xml"></mapper>-->
<package name="com.lanhuigu.mybatis.mapper"/>
</mappers>
</configuration>
主要将properties增加property属性,将数据库连接用户名和密码设置成属性值。这个时候dataSource连接同样正常,因为资源文件加载时是先从properties下的property去查找jdbc.username,jdbc.password,如果找到优先读取,然后再从jdbc.properties中去读取jdbc.username,jdbc.password,如果读取到,就用配置文件的,但是没有读到,这个时候dataSource就用property中的jdbc.username,jdbc.password作为数据库连接名和密码。
实验二:
修改jdbc.properties为:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456
mybatis-config.xml中的properties配置修改,主要将property中jdbc.password的value值给定一个错误的密码:
<properties resource="jdbc.properties">
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="abcdefgh"/>
</properties>
这个时候数据库连接正常,刚好印证了实验一中文件读取使用优先级。先从property中读取jdbc.password,然后再去test-jdbc.properties中读取jdbc.password,如果没有读到,dataSource就用property下的jdbc.password作为连接密码,但是,如果在test-jdbc.properties中读到jdbc.password,将会覆盖掉property中的jdbc.password,在dataSource中就会采用最后确定的test-jdbc.properties中的jdbc.password做为连接密码,虽然property下的jdbc.password是错的,但是test-jdbc.propertiest中的jdbc.password是对的,覆盖掉property中的,所以,能保证数据库还能正常连接。
properties总结:
如果属性不只一个地方进行了配置,那么 MyBatis 将按照下面的顺序来加载:
在 properties 元素体内指定的属性首先被读取。
然后根据 properties 元素中的 resource 属性读取类路径下属性文件或根据 url 属性指定的路径读取属性文件,
并覆盖已读取的同名属性。
最后读取作为方法参数传递的属性,并覆盖已读取的同名属性。
因此,通过方法参数传递的属性具有最高优先级,resource/url属性中指定的配置文件次之,最低优先级的是properties属性中指定的属性。
2、settings(设置)
配置参考实例:每个设置名的含义查看官网:mybatis – MyBatis 3 | 配置
<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>
3、typeAliases(类型别名)
类型别名是为Java类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
<typeAliases>
<typeAlias alias="User" type="com.lanhuigu.mybatis.entity.User"/>
</typeAliases>
当这样配置时,User可以用在任何使用com.lanhuigu.mybatis.entity.User的地方。
没有配置之前:映射文件配置如下,UseMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lanhuigu.mybatis.map.UserMapper">
<select id="queryUserById" parameterType="int"
resultType="com.lanhuigu.mybatis.entity.User">
select
id,
userName,
age
from user
where id = #{id}
</select>
</mapper>
但是我们在mybatis-config.xml中给com.lanhuigu.mybatis.entity.User指定别名后,任何使用com.lanhuigu.mybatis.entity.User的地方都可以换成User,
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="User">
<select id="queryUserById" parameterType="int"
resultType="User">
select
id,
userName,
age
from user
where id = #{id}
</select>
</mapper>
其实就是别名概念的使用,在数据库中,查询字段太长也会取个别名,含义都一样。已经为许多常见的Java类型内建了相应的类型别名。它们都是大小写不敏感的,需要注意的是由基本类型名称重复导致的特殊处理。
别名 | 映射的类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer ... | int ........ |
4、typeHandlers(类型处理器)
无论是MyBatis在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成Java类型。下表描述了一些默认的类型处理器。假如不自定义的话,是不需要配置的。
在 MyBatis 中有许多自带的类型处理器,但有时候也会满足不了开发的需求,这时候就需要配置自己的类型处理器了,而 typeHandlers 标签就是用来声明自己的类型处理器的。
如何使用?如何配置:使用 typeHandlers 标签配置一个自己的类型处理器,一般需要三个步骤
(1)编写类型处理器类
例如要编写一个将 JDBC 的 timestamp 类型与 Date 类型相互转换的类型处理器配置示例。首先编写类型处理器,一般要实现 org.apache.ibatis.type.TypeHandler 接口,接口的泛型指定要转换的 Java 参数类型,若不指定则默认为 Object 类,实现 TypeHandler 接口主要改写四个方法,如下:
public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
public String getResult(ResultSet rs,String columnName)
public String getResult(ResultSet rs,int columnIndex)
public String getResult(CallableStatement cs,int columnIndex)
setParameter 方法是在 sql 配置传入参数时(新增、删除、修改、查询)执行的操作,可以在将参数传入数据库之前在该方法中对数据类型做处理。
另外三个 getResult 方法则在数据库返回结果时,将结果信息转换为相应的 Java 类型。区别在于前两个 getResult 方法供普通 select 方法使用,一个根据字段名,一个根据字段下标来获取数据,最后一个 getResult 方法供存储过程使用,根据字段下标获取数据。
代码示例:
package cn.com.mybatis.test;
import java.sql.CallableStatement;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.JdbcType;
public class DateTypeHandler implements TypeHandler<Date> {
//转换日期类型的辅助类
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public void setParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException{
//指定传入的Java参数对应JDBC中的数据库类型
System.out.println("其他逻辑");
ps.setDate(i, parameter);
System.out.println("其他逻辑");
}
public Date getResult(ResultSet rs,String columnName) throws SQLException{
System.out.println("其他逻辑");
return rs.getDate(columnName);
}
public Date getResult(ResultSet rs,int columnIndex) throws SQLException{
System.out.println("其他逻辑");
return rs.getDate(columnIndex);
}
public Date getResult(CallableStatement cs,int columnIndex) throws SQLException{
System.out.println("其他逻辑");
return cs.getDate(columnIndex);
}
}
(2)在 MyBatis 全局配置文件中配置该类型处理器
之后在 MyBatis 的全局配置文件 SqlMapConfig 中使用 typeHandlers 标签来注册类型处理器,示例代码如下:
<typeHandlers>
<typeHandler handler="cn.com.mybatis.test.DateTypeHandler" javaType="java.util.Date" jdbcType="TIMESTAMP"/>
</typeHandlers>
(3)在 sql 映射配置文件中使用
然后在 sql 映射文件 xxxMapper.xml 中的 sql 语句中添加自定义的类型处理器的处理配置即可,代码示例如下:
insert into user(username,password,regdate) value(#{username},#{password},
#{regdate,javaType=date,jdbcType=TIMESTAMP,
typeHandler=cn.com.mybatis.test.DateTypeHandler})