MyBatis的配置文件将会对MyBatis体系产生深远的影响,我们先来浏览下MyBatis配置XML文件的层次结构,注意这些层次是不能够颠倒顺序的。我们按配置的先后顺序一一给大家解析。
<?xml version="1.0" encoding="UTF-8"?>
<configuration><!--配置-->
<properties/><!--属性-->
<settings/><!--设置-->
<typeAliases/><!--类型命名、别名-->
<typeHandlers/><!--类型处理器-->
<objectFactory/><!--对象工厂-->
<plugins/><!--插件-->
<environments><!--配置环境-->
<environment>
<transactionManager/><!--事务管理器-->
<dataSource/><!--数据源-->
</environment>
</environments>
<databaseIdProvider/><!--数据库厂商标识-->
<mappers/><!--映射器-->
</configuration>
一:properties配置属性的元素
<properties>
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/dataBasename"></property>
<property name="username" value="root"></property>
<property name="password" value="1"></property>
</properties>
<dataSource type="POOLED">
<property name="driver" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</dataSource>
更多时候我们希望使用properties文件来配置文件的配置属性值,以便我们在多个配置文件中使用它们,也方便日后维护修改,如下:
#数据库配置文件
driver=come.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/dateBaseName
username=root
password=1
我们把这个配置文件放在源包下,引入配置文件
<properties resource="jdbc.properties"/>
优先级:方法参数传递的属性 > properties文件传递的参数 > properties元素内指定的参数
二:setting设置MyBatis的运行时行为
即使不配置setting,MyBatis也可以正常的工作(使用默认值)
三:typeAliases别名
别名,因为我们遇到的类全限定名过长,所以我们希望用一个简短的名称去指代它,而这个名称可以在MyBatis上下文中使用,别名再MyBatis里面分为系统定义别名
和自定义别名两类,是不区分大小写的,一个typeAliaes的实例是在解析配置文件的时生成的,然后长期保存在Configuration对象中,当我们使用它时,再把它们拿出来,
这样就没有必要每次重新生成了。
(1)系统定义别名
基本数据类型bytelong、int、boolean.....使用_byte、_long、_int、_boolean.....
引用数据类型Byte、Integer、Boolean、Map、List、ArrayList、Collection、.....使用byte、integer、boolean、map、list、arraylist、collection.....
(2)自定义别名
<typeAliases>
<typeAlias alias="role" type="com.kang.chapter4.Role"/>
</typeAliases>
自动扫描的形式:
<typeAliase>
<package name="com.kang.chapter4">
<package name="com.kang.chapter5">
<package name="com.kang.chapter6">
</typeAliase>
在对应的POJO上使用注解@Alias即可。不写@Alias的POJO也会被装载,将以类名的第一个字母变为小写作为MyBatis的别名
四:typeHandler类型处理器
typeHandler的常用配置为Java类型(javaType)、JDBC类型(jdbcType)。typeHandler的作用就是将参数从javaType转换为jdbcType或者从数据库取出结果时
把jdbcType转换为javaType。
1、系统定义的typeHandler
MyBatis系统内已经为我们定义了一系列的typeHandler,一般情况下这些typeHandler已经能够应付大部分的场景了我们来列举几个
类型处理器 Java类型 JDBC类型
StringTypeHandler java.lang.String CHAR,VARCHAR
ClobTypeHandler java.lang.String CLOB,LONGVARCHAR
查看StringTypeHandler原码发现,StringTypeHandler继承了BaseTypeHandler,而BaseTypeHandler实现了接口typeHandler,并且自定义了4个抽象方法。
2、自定义typeHandler
一般情况下不需要写自定义的typeHandler,这里让我们来重新覆盖一个字符串的typeHandler,首先先配置XML文件,确定我们需要处理什么类型的参数和结果
<typeHandlers>
<typeHandler jdbcType="VARCHAR" javaType="string" handler="com.kang.typeHandler.MyStringTypeHandler"/>
</typeHandlers>
对于MyStringTypeHandler我们要必须实现接口:org.apache.ibatis.type.TypeHandler,在MyBatis中,我们也可以继承org.apache.ibatis.type.BaseTypeHandler来实现,
因为BaseTypeHandler已经实现了typehandler接口。
MyStringTypeHandler中用注解@MappedTypes来定义JavaType用@MappedJdbcTypes({String.class})定义JdbcTyepe({JdbcType.VARCHAR})
最后我们要去标识哪些参数或者结果类型使用typeHandler进行转换,
<resultMap type="role" id="roleMap">
<id column="id" property="id" jdbcType="BIGINT" javaType="long"/>
<result column="role_name" property="roleName" javaType="string" jdbcType="VARCHAR">
<result column="note" property="note" typehandler="com.kang.typeHandler.MyStringTypeHandler"/>
</resultMap>
<selectm id="findRole" parameterType="string" resultMap="roleMap">
select id,role_name,note from t_role
where 1=1 and role_name like concat('%',#{roleName javaType=string,jdbcType=VARCHAR,typeHandler=com.kang.typeHandler.MyStringTypeHandler},'%')
</select>
这里我们提供了三个typeHandler的使用方法
在配置文件中配置,在结果集里面的roleName定义javaType金额jdbcType和我们定义在配置文件里面的typeHandler一致,MyBatis就能够知道使用我们自定义的typeHandler进行转化;
映射集里面直接定义具体的typeHandler,这样就不需要再定义其他参数了;
在参数中制定typeHandler,这样就会用对应的typeHandler进行转化,也不需要再定义其他参数
可以使用包扫描的方式,减少配置工作
<typeHandlers>
<package name="com.kang.typeHandler"/>
<typeHandlers/>
3、枚举类型typeHandler
枚举类型typeHandler有自己特殊的规则,MyBatis内部提供了两个转化枚举类型的typeHandler给我们使用。
org.apache.ibatis.type.EnumTypeHandler 用枚举字符串名称作为参数传递
org.apache.ibatis.type.EnumOrdinalTypeHandler 用整数下标作为参数传递
A:写一个简单的枚举类
public enum Sex{
MALE(1,"男"),FEMALE(2,"女");
private int id;
private String name;
get\set
and constraction
}
B:配置性别枚举
<typeHandlers>
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.kang.enums.Sex">
</typeHandler>
</typeHandlers>
C:在Mapper文件中配置typeHandler
<resultMap>
<result column="sex" property="sex" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler">
......
</resultMap>
即可,EnumTypeHandler同理,只要修改EnumTypeHandler对应的字段类型即可
自定义枚举类型的typeHandler
A:
<typeHandler handler="com.kang.type.SexEnumTypeHander" javaType="com.kang.enum.Sex"/>
B:给出SexEnumTypeHander的实现类
public class SexEnumTypeHander implements TypeHandler<Sex>{
......
}
C:
<resultMap>
<result column="sex" property="sex" typeHandler="com.kang.type.SexEnumTypeHander">
......
</resultMap>
五:ObjectFactory
当MyBatis在构建一个结果返回的时候,都会使用ObjectFactory去构建POJO,在MyBatis中可以定制自己的对象工厂。一般来说,使用默认的ObjectFactory即可。
如需特定对象工厂按以下配置
<objectFactory type="com.kang.objectFactory.MyObjectFactory">
<property name="name" value="MyObjectFactory"/>
</objectFactory>
MyObjectFactory 要实现ObjectFactory接口或者继承DefaultObjectFactory;
六:plugins跳过
七:environments配置环境
配置环境可以注册多个数据源(dataSource),每个数据源分为两大部分:一个是数据库源一个是数据库事务管理
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="autoCommit" value="false"></property>
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="......"/>
<property name="username" value="root"/>
<property name="password" value="1"/>
</dataSource>
</environment>
</environments>
environments中的属性default指定的是启用哪个数据源,environment中的id是数据源的标识
transactionManager配置的是数据库事务,其中type属性有3种配置方式。
(1)JDBC,采用JDBC方式管理事务,在独立编码中我们常使用;
(2)MANAGED,采用容器方式管理事务,在JNDI数据源中常用
(3)自定义事务,由使用者自定义事务管理办法,特殊情况下使用
property元素配置数据库各项属性
DataSource配置数据源的连接的信息,type属性是提供我们队数据库连接方式的配置,同样MyBatis提供这么几种配置方式
(1)UNPOOLED,非数据库连接池
(2)POOLED,数据库连接池
(3)JNDI,JNDI数据源
(4)自定义数据源
自定义数据源,比如我们要采取DBCP数据源,则我们要先实现org.apache.ibatis.dataSource.DataSourceFactory接口,如下
public class DbcpDataSourceFactory extends BasicDataSource implements DataSourceFactory{
......
}
<dataSource type="com.kang.DbcpDataSourceFactory"></dataSource>
八:databaseIdProvider数据库厂商标识
在实际情况中,一个系统可能同时支持不同的数据库,此时,根据不同的数据库厂商标识调取的SQL就应该不一样,于是就有了这个databaseIdProvider数据库厂商标识
MyBatis自己提供了默认的配置规则,如下
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver">
<property name="MySQL" Server" value="mysql">
<property name="DB2" Server" value="db2">
<property name="Oracle" value="oracle">
</databaseIdProvider>
type="DB_VENDOR" 是启用启用MyBatis内部的注册的策略器,首先,MyBatis会将配置文件读入到Configuration对象立面,在连接数据库后去调用getDatabaseProductName()
获得数据库的信息,然后我们在配置文件中根据调取的返回值,取到value。我们在SQL中指定哪个数据库厂商执行,如下:
<select id="getRole" parameterType="string" resultType="role" databaseId="mysql">
select role_name,role_id from t_role where 1=1 and role_id=#{id}
</select>
在多了一个databaseId属性后,MyBatis提供如下规则。
(1)如果没有配置databaseIdProvider标签,则Configuration中的databaseId为null。
(2)如果配置了databaseIdProvider标签,MyBatis就会用配置的name值去匹配数据库信息,如果配的上就会设置Configuration的databaseId值,否则为null;
(3)如果Configuration中的databaseId不为空,则它只会找到配置databaseId的SQL语句。
(4)MyBatis会加载不带databaseId属性和带有匹配当前数据库databaseId属性的所有语句。如果同时找到带有databaseId和不带databaseId的相同语句,则后者会被抛;
自定义策略器,实现databaseIdProvider接口,并且实现配置
public class MydatabaseIdProvider implements DatabaseIdProvider{
......
}
<databaseIdProvider type="com.kang.MydatabaseIdProvider">
<property name="SQL Server" value="sqlserver">
<property name="MySQL" Server" value="mysql">
<property name="DB2" Server" value="db2">
<property name="Oracle" value="oracle">
</databaseIdProvider>
九:引入映射器
(1)定义映射器接口
public interface RoleMapper{
public Role getRole(Long id);
}
(2)定义Mapper映射器
......
<mapper namespace="com.kang.mapper.RoleMapper">
<select id="getRole" parameterType="long" resultType="com.kang.Role">
select id,role_name from t_role where 1=1 and id=#{id}
</select>
</mapper>
(3)引入映射器
A:文件路径引入:
<mappers>
<mapper resource="com/kang/mapper/roleMapper.xml"/>
</mappers>
B:包名引入映射器
<mappers>
<package name="com.kang.mapper">
</mappers>
C:类注册引入映射器
<mappers>
<mapper class="com.kang.mapper.RoleMapper"></mapper>
</mappers>
D:用userMapper.xml引入映射器
<mappers>
<mapper url="file:///var/mappers/com/kang/roleMapper.xml"/>
</mappers>
<?xml version="1.0" encoding="UTF-8"?>
<configuration><!--配置-->
<properties/><!--属性-->
<settings/><!--设置-->
<typeAliases/><!--类型命名、别名-->
<typeHandlers/><!--类型处理器-->
<objectFactory/><!--对象工厂-->
<plugins/><!--插件-->
<environments><!--配置环境-->
<environment>
<transactionManager/><!--事务管理器-->
<dataSource/><!--数据源-->
</environment>
</environments>
<databaseIdProvider/><!--数据库厂商标识-->
<mappers/><!--映射器-->
</configuration>
一:properties配置属性的元素
<properties>
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/dataBasename"></property>
<property name="username" value="root"></property>
<property name="password" value="1"></property>
</properties>
<dataSource type="POOLED">
<property name="driver" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</dataSource>
更多时候我们希望使用properties文件来配置文件的配置属性值,以便我们在多个配置文件中使用它们,也方便日后维护修改,如下:
#数据库配置文件
driver=come.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/dateBaseName
username=root
password=1
我们把这个配置文件放在源包下,引入配置文件
<properties resource="jdbc.properties"/>
优先级:方法参数传递的属性 > properties文件传递的参数 > properties元素内指定的参数
二:setting设置MyBatis的运行时行为
即使不配置setting,MyBatis也可以正常的工作(使用默认值)
三:typeAliases别名
别名,因为我们遇到的类全限定名过长,所以我们希望用一个简短的名称去指代它,而这个名称可以在MyBatis上下文中使用,别名再MyBatis里面分为系统定义别名
和自定义别名两类,是不区分大小写的,一个typeAliaes的实例是在解析配置文件的时生成的,然后长期保存在Configuration对象中,当我们使用它时,再把它们拿出来,
这样就没有必要每次重新生成了。
(1)系统定义别名
基本数据类型bytelong、int、boolean.....使用_byte、_long、_int、_boolean.....
引用数据类型Byte、Integer、Boolean、Map、List、ArrayList、Collection、.....使用byte、integer、boolean、map、list、arraylist、collection.....
(2)自定义别名
<typeAliases>
<typeAlias alias="role" type="com.kang.chapter4.Role"/>
</typeAliases>
自动扫描的形式:
<typeAliase>
<package name="com.kang.chapter4">
<package name="com.kang.chapter5">
<package name="com.kang.chapter6">
</typeAliase>
在对应的POJO上使用注解@Alias即可。不写@Alias的POJO也会被装载,将以类名的第一个字母变为小写作为MyBatis的别名
四:typeHandler类型处理器
typeHandler的常用配置为Java类型(javaType)、JDBC类型(jdbcType)。typeHandler的作用就是将参数从javaType转换为jdbcType或者从数据库取出结果时
把jdbcType转换为javaType。
1、系统定义的typeHandler
MyBatis系统内已经为我们定义了一系列的typeHandler,一般情况下这些typeHandler已经能够应付大部分的场景了我们来列举几个
类型处理器 Java类型 JDBC类型
StringTypeHandler java.lang.String CHAR,VARCHAR
ClobTypeHandler java.lang.String CLOB,LONGVARCHAR
查看StringTypeHandler原码发现,StringTypeHandler继承了BaseTypeHandler,而BaseTypeHandler实现了接口typeHandler,并且自定义了4个抽象方法。
2、自定义typeHandler
一般情况下不需要写自定义的typeHandler,这里让我们来重新覆盖一个字符串的typeHandler,首先先配置XML文件,确定我们需要处理什么类型的参数和结果
<typeHandlers>
<typeHandler jdbcType="VARCHAR" javaType="string" handler="com.kang.typeHandler.MyStringTypeHandler"/>
</typeHandlers>
对于MyStringTypeHandler我们要必须实现接口:org.apache.ibatis.type.TypeHandler,在MyBatis中,我们也可以继承org.apache.ibatis.type.BaseTypeHandler来实现,
因为BaseTypeHandler已经实现了typehandler接口。
MyStringTypeHandler中用注解@MappedTypes来定义JavaType用@MappedJdbcTypes({String.class})定义JdbcTyepe({JdbcType.VARCHAR})
最后我们要去标识哪些参数或者结果类型使用typeHandler进行转换,
<resultMap type="role" id="roleMap">
<id column="id" property="id" jdbcType="BIGINT" javaType="long"/>
<result column="role_name" property="roleName" javaType="string" jdbcType="VARCHAR">
<result column="note" property="note" typehandler="com.kang.typeHandler.MyStringTypeHandler"/>
</resultMap>
<selectm id="findRole" parameterType="string" resultMap="roleMap">
select id,role_name,note from t_role
where 1=1 and role_name like concat('%',#{roleName javaType=string,jdbcType=VARCHAR,typeHandler=com.kang.typeHandler.MyStringTypeHandler},'%')
</select>
这里我们提供了三个typeHandler的使用方法
在配置文件中配置,在结果集里面的roleName定义javaType金额jdbcType和我们定义在配置文件里面的typeHandler一致,MyBatis就能够知道使用我们自定义的typeHandler进行转化;
映射集里面直接定义具体的typeHandler,这样就不需要再定义其他参数了;
在参数中制定typeHandler,这样就会用对应的typeHandler进行转化,也不需要再定义其他参数
可以使用包扫描的方式,减少配置工作
<typeHandlers>
<package name="com.kang.typeHandler"/>
<typeHandlers/>
3、枚举类型typeHandler
枚举类型typeHandler有自己特殊的规则,MyBatis内部提供了两个转化枚举类型的typeHandler给我们使用。
org.apache.ibatis.type.EnumTypeHandler 用枚举字符串名称作为参数传递
org.apache.ibatis.type.EnumOrdinalTypeHandler 用整数下标作为参数传递
A:写一个简单的枚举类
public enum Sex{
MALE(1,"男"),FEMALE(2,"女");
private int id;
private String name;
get\set
and constraction
}
B:配置性别枚举
<typeHandlers>
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.kang.enums.Sex">
</typeHandler>
</typeHandlers>
C:在Mapper文件中配置typeHandler
<resultMap>
<result column="sex" property="sex" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler">
......
</resultMap>
即可,EnumTypeHandler同理,只要修改EnumTypeHandler对应的字段类型即可
自定义枚举类型的typeHandler
A:
<typeHandler handler="com.kang.type.SexEnumTypeHander" javaType="com.kang.enum.Sex"/>
B:给出SexEnumTypeHander的实现类
public class SexEnumTypeHander implements TypeHandler<Sex>{
......
}
C:
<resultMap>
<result column="sex" property="sex" typeHandler="com.kang.type.SexEnumTypeHander">
......
</resultMap>
五:ObjectFactory
当MyBatis在构建一个结果返回的时候,都会使用ObjectFactory去构建POJO,在MyBatis中可以定制自己的对象工厂。一般来说,使用默认的ObjectFactory即可。
如需特定对象工厂按以下配置
<objectFactory type="com.kang.objectFactory.MyObjectFactory">
<property name="name" value="MyObjectFactory"/>
</objectFactory>
MyObjectFactory 要实现ObjectFactory接口或者继承DefaultObjectFactory;
六:plugins跳过
七:environments配置环境
配置环境可以注册多个数据源(dataSource),每个数据源分为两大部分:一个是数据库源一个是数据库事务管理
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="autoCommit" value="false"></property>
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="......"/>
<property name="username" value="root"/>
<property name="password" value="1"/>
</dataSource>
</environment>
</environments>
environments中的属性default指定的是启用哪个数据源,environment中的id是数据源的标识
transactionManager配置的是数据库事务,其中type属性有3种配置方式。
(1)JDBC,采用JDBC方式管理事务,在独立编码中我们常使用;
(2)MANAGED,采用容器方式管理事务,在JNDI数据源中常用
(3)自定义事务,由使用者自定义事务管理办法,特殊情况下使用
property元素配置数据库各项属性
DataSource配置数据源的连接的信息,type属性是提供我们队数据库连接方式的配置,同样MyBatis提供这么几种配置方式
(1)UNPOOLED,非数据库连接池
(2)POOLED,数据库连接池
(3)JNDI,JNDI数据源
(4)自定义数据源
自定义数据源,比如我们要采取DBCP数据源,则我们要先实现org.apache.ibatis.dataSource.DataSourceFactory接口,如下
public class DbcpDataSourceFactory extends BasicDataSource implements DataSourceFactory{
......
}
<dataSource type="com.kang.DbcpDataSourceFactory"></dataSource>
八:databaseIdProvider数据库厂商标识
在实际情况中,一个系统可能同时支持不同的数据库,此时,根据不同的数据库厂商标识调取的SQL就应该不一样,于是就有了这个databaseIdProvider数据库厂商标识
MyBatis自己提供了默认的配置规则,如下
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver">
<property name="MySQL" Server" value="mysql">
<property name="DB2" Server" value="db2">
<property name="Oracle" value="oracle">
</databaseIdProvider>
type="DB_VENDOR" 是启用启用MyBatis内部的注册的策略器,首先,MyBatis会将配置文件读入到Configuration对象立面,在连接数据库后去调用getDatabaseProductName()
获得数据库的信息,然后我们在配置文件中根据调取的返回值,取到value。我们在SQL中指定哪个数据库厂商执行,如下:
<select id="getRole" parameterType="string" resultType="role" databaseId="mysql">
select role_name,role_id from t_role where 1=1 and role_id=#{id}
</select>
在多了一个databaseId属性后,MyBatis提供如下规则。
(1)如果没有配置databaseIdProvider标签,则Configuration中的databaseId为null。
(2)如果配置了databaseIdProvider标签,MyBatis就会用配置的name值去匹配数据库信息,如果配的上就会设置Configuration的databaseId值,否则为null;
(3)如果Configuration中的databaseId不为空,则它只会找到配置databaseId的SQL语句。
(4)MyBatis会加载不带databaseId属性和带有匹配当前数据库databaseId属性的所有语句。如果同时找到带有databaseId和不带databaseId的相同语句,则后者会被抛;
自定义策略器,实现databaseIdProvider接口,并且实现配置
public class MydatabaseIdProvider implements DatabaseIdProvider{
......
}
<databaseIdProvider type="com.kang.MydatabaseIdProvider">
<property name="SQL Server" value="sqlserver">
<property name="MySQL" Server" value="mysql">
<property name="DB2" Server" value="db2">
<property name="Oracle" value="oracle">
</databaseIdProvider>
九:引入映射器
(1)定义映射器接口
public interface RoleMapper{
public Role getRole(Long id);
}
(2)定义Mapper映射器
......
<mapper namespace="com.kang.mapper.RoleMapper">
<select id="getRole" parameterType="long" resultType="com.kang.Role">
select id,role_name from t_role where 1=1 and id=#{id}
</select>
</mapper>
(3)引入映射器
A:文件路径引入:
<mappers>
<mapper resource="com/kang/mapper/roleMapper.xml"/>
</mappers>
B:包名引入映射器
<mappers>
<package name="com.kang.mapper">
</mappers>
C:类注册引入映射器
<mappers>
<mapper class="com.kang.mapper.RoleMapper"></mapper>
</mappers>
D:用userMapper.xml引入映射器
<mappers>
<mapper url="file:///var/mappers/com/kang/roleMapper.xml"/>
</mappers>