三、Mybatis 核心配置文件
MyBatis的全局配置文件mybatis-config.xml,配置内容如下:
-  properties(属性) 
-  settings(全局配置参数) 
-  typeAliases(类型别名) 
-  typeHandlers(类型处理器) 
-  objectFactory(对象工厂) 
-  plugins(插件) 
-  environments(环境集合属性对象) -  environment(环境子属性对象) -  transactionManager(事务管理) 
-  dataSource(数据源) 
 
-  
 
-  
-  mappers(映射器) 
3.1 properties属性
将数据库连接参数单独配置在db.properties中,只需要在mybatis-config.xml中加载db.properties的属性值。在mybatis-config.xml中就不需要对数据库连接参数硬编码。
# Oracle相关配置
jdbc.oracle.driver=oracle.jdbc.driver.OracleDriver
jdbc.oracle.url=jdbc:oracle:thin:@localhost:1521:orcl
jdbc.oracle.username=scott
jdbc.oracle.password=tiger
# Mysql相关配置
jdbc.mysql.driver=com.mysql.jdbc.Driver
jdbc.mysql.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&useSSL=false
jdbc.mysql.username=root
jdbc.mysql.password=root使用 <properties> 标签加载属性文件:
-  resource: 从classpath下读取资源文件 -  classpath为maven项目中的src/main/resources目录 + src/main/java目录,编译之后的目录为target/classes; 
 
-  
-  url: 从当前系统环境的文件系统中读取资源 -  windows: d:/conf/test.properties 
-  linux: /home/tom/conf/test.properties 
 
-  
<!-- 加载外部资源文件 -->
<properties resource="db.properties">
    <!--properties中还可以配置一些属性-->
    <!--<property name="mysql.url" value="jdbc:mysql://localhost:3306/ssm"/>-->
</properties>在环境中使用:
<environments default="mysql">
    <environment id="mysql">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.mysql.driver}"/>
            <property name="url" value="${jdbc.mysql.url}"/>
            <property name="username" value="${jdbc.mysql.username}"/>
            <property name="password" value="${jdbc.mysql.password}"/>
        </dataSource>
    </environment>
</environments>注意:MyBatis将按照下面的顺序来加载属性
-  在properties标签体内定义的属性首先被读取; 
-  然后会读取properties标签中resource或url加载的属性,它会覆盖已读取的同名属性; 
-  最后读取parameterType传递的属性,它会覆盖已读取的同名属性; 
建议:
-  不要在properties标签体内添加任何属性值,只将属性值定义在properties文件中; 
-  在properties文件中定义属性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX; 
3.2 settings全局配置参数
MyBatis框架在运行时可以调整一些运行参数,比如:开启二级缓存、开启延迟加载。
可配置参数如下:
| 设置 | 描述 | 有效值 | 默认值 | 
|---|---|---|---|
| cacheEnabled | 在全局范围内启用或禁用缓存配置任何映射器在此配置下。 | true, false | true | 
| lazyLoadingEnabled | 在全局范围内启用或禁用延迟加裁。禁用时,所有将会将热加载。 | true, false | false | 
| aggressiveLazyLoading | 当开启时,任何方法的调用都会加载该对象的所有属性。 | true, false | 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 | 
| autoMappingUnknownColumnBehavior | 指定发现自动映射目标未知列(或者未知属性类型)的行为。NONE: 不做任何反应;WARNING: 输出提醒日志 ('AutoMappingUnknownColumnBehavior'的日志等级必须设置为 WARN);FAILING: 映射失败 (抛出 SqlSessionException)。 | NONE, WARNING, FAILING | NONE | 
| defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。 | SIMPLE, REUSE, BATCH | SIMPLE | 
| defaultStatementTimeout | 设置超时时间,它决定驱动等待数据库响应的秒数。 | 任意正整数 | 未设置 | 
| defaultFetchSize | 为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。 | 任意正整数 | 未设置 | 
| safeRowBoundsEnabled | 允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 | true, false | false | 
| safeResultHandlerEnabled | 允许在嵌套语句中使用分页(ResultHandler)。如果允许使用则设置为 false。 | true, false | true | 
| mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 | true, false | false | 
| localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 | SESSION, STATEMENT | SESSION | 
| jdbcTypeForNull | 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType 常量,常用值:NULL, VARCHAR 或 OTHER | OTHER | 
| lazyLoadTriggerMethods | 指定哪个对象的方法触发一次延迟加载。 | 用逗号分隔的方法列表 | equals,clone,hashCode,toString | 
| defaultScriptingLanguage | 指定动态 SQL 生成的默认语言。 | 一个类型别名或完全限定类名 | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver | 
| defaultEnumTypeHandler | 指定 Enum 使用的默认 TypeHandler 。 | 一个类型别名或完全限定类名 | org.apache.ibatis.type.EnumTypeHandler | 
| callSettersOnNulls | 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值初始化的时候比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。 | true, false | false | 
| returnInstanceForEmptyRow | 当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集 (如集合或关联)。 | true, false | false | 
| logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | 任何字符串 | 未设置 | 
| logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J, LOG4J, LOG4J2, JDK_LOGGING, COMMONS_LOGGING, STDOUT_LOGGING, NO_LOGGING | 未设置 | 
| proxyFactory | 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 | CGLIB, JAVASSIST | JAVASSIST | 
| vfsImpl | 指定 VFS 的实现。 | 自定义 VFS 的实现的类全限定名,以逗号分隔 | 未设置 | 
| useActualParamName | 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters选项。 | true, false | true | 
| configurationFactory | 指定一个提供 Configuration实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration()的方法。 | 类型别名或者全类名 | 未设置 | 
开启下划线与驼峰命名的转换:
<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>3.3 typeAliases类型别名
在mapper.xml中,定义很多的statement。statement需要parameterType指定输入参数的类型、需要resultType指定输出结果的映射类型。如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发。
3.3.1 MyBatis默认支持别名
| 别名 | 映射的类型 | 别名 | 映射的类型 | 
|---|---|---|---|
| _byte | byte | byte | java.lang.Byte | 
| _short | short | short | java.lang.Short | 
| _int | int | int | java.lang.Integer | 
| _integer | int | integer | java.lang.Integer | 
| _long | long | long | java.lang.Long | 
| _float | float | float | java.lang.Float | 
| _double | double | double | java.lang.Double | 
| _boolean | boolean | boolean | java.lang.Boolean | 
| string | java.lang.String | date | java.util.Date | 
| map | java.util.Map | hashmap | java.util.HashMap | 
| list | java.util.List | arraylist | java.util.ArrayList | 
| object | java.lang.Object | 
3.3.2 自定义别名
单个定义别名:
    单个类型的别名配置:typeAlias。
         type:类型,java中类的全限定名;
         alias:别名;
<typeAliases>
    <typeAlias type="com.newcapec.entity.Dept" alias="dd"/>
</typeAliases>批量定义别名:
    批量类型别名的配置:package。
         name:需要配置别名的类所在的包;
         设置包名之后,此包下所有的类都拥有类型别名,其别名为:该类的类名,首字母大小均可。
<typeAliases>
    <!--
        <package> 批量别名配置
        name:需要配置别名的实体类所在包的包名
        默认别名为该类的类名,其首字母大小均可
    -->
    <package name="com.newcapec.entity"/>
</typeAliases>注解定义别名:
在实体类上可以使用 @Alias("name") 注解来标识该类的别名。
@Alias("depart")
public class Dept {
    //...
}注意:配置和注解仅能使用一种方式,当注解存在时,则其别名为其注解值。
3.3.3 应用
实体类:
public class Dept {
    private Integer deptno;
    private String dname;
    private String loc;
    public Integer getDeptno() {
        return deptno;
    }
    public void setDeptno(Integer deptno) {
        this.deptno = deptno;
    }
    public String getDname() {
        return dname;
    }
    public void setDname(String dname) {
        this.dname = dname;
    }
    public String getLoc() {
        return loc;
    }
    public void setLoc(String loc) {
        this.loc = loc;
    }
    @Override
    public String toString() {
        return "Dept{" +
            "deptno=" + deptno +
            ", dname='" + dname + '\'' +
            ", loc='" + loc + '\'' +
            '}';
    }
}接口:
package com.newcapec.mapper;
import com.newcapec.entity.Dept;
import java.util.List;
public interface DeptMapper {
    List<Dept> select();
    Dept selectById(Integer deptno);
    List<Dept> selectByDname(String dname);
}mapper文件:
<?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.newcapec.mapper.DeptMapper">
    <select id="select" resultType="dd">
        select deptno,dname,loc from dept
    </select>
    <select id="selectById" parameterType="int" resultType="dept">
        select deptno,dname,loc from dept where deptno=#{deptno}
    </select>
    <select id="selectByDname" parameterType="string" resultType="Dept">
        select deptno,dname,loc from dept where dname=#{dname}
    </select>
</mapper>测试:
package com.newcapec;
import com.newcapec.entity.Dept;
import com.newcapec.mapper.DeptMapper;
import com.newcapec.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
/**
 * 别名测试
 */
public class TypeAliasTest {
    @Test
    public void testSelect() {
        SqlSession sqlSession = MybatisUtil.getSession();
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> list = deptMapper.select();
        for (Dept dept : list) {
            System.out.println(dept);
        }
        sqlSession.close();
    }
    @Test
    public void testSelectById() {
        SqlSession sqlSession = MybatisUtil.getSession();
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        Dept dept = deptMapper.selectById(10);
        System.out.println(dept);
        sqlSession.close();
    }
    @Test
    public void testSelectByDname() {
        SqlSession sqlSession = MybatisUtil.getSession();
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> list = deptMapper.selectByDname("ACCOUNTING");
        System.out.println(list);
        sqlSession.close();
    }
}3.4 typeHandlers类型处理器
MyBatis中通过typeHandlers完成jdbc类型和Java类型的转换,MyBatis自带的类型处理器基本上满足日常需求,不需要单独定义。
MyBatis支持类型处理器:
| 类型处理器 | Java类型 | JDBC类型 | 
|---|---|---|
| BooleanTypeHandler | Boolean,boolean | 任何兼容的布尔值 | 
| ByteTypeHandler | Byte,byte | 任何兼容的数字或字节类型 | 
| ShortTypeHandler | Short,short | 任何兼容的数字或短整型 | 
| IntegerTypeHandler | Integer,int | 任何兼容的数字和整型 | 
| LongTypeHandler | Long,long | 任何兼容的数字或长整型 | 
| FloatTypeHandler | Float,float | 任何兼容的数字或单精度浮点型 | 
| DoubleTypeHandler | Double,double | 任何兼容的数字或双精度浮点型 | 
| BigDecimalTypeHandler | BigDecimal | 任何兼容的数字或十进制小数类型 | 
| StringTypeHandler | String | CHAR和VARCHAR类型 | 
| ClobTypeHandler | String | CLOB和LONGVARCHAR类型 | 
| NStringTypeHandler | String | NVARCHAR和NCHAR类型 | 
| NClobTypeHandler | String | NCLOB类型 | 
| ByteArrayTypeHandler | byte[] | 任何兼容的字节流类型 | 
| BlobTypeHandler | byte[] | BLOB和LONGVARBINARY类型 | 
| DateTypeHandler | java.util.Date | TIMESTAMP类型 | 
| DateOnlyTypeHandler | java.util.Date | DATE类型 | 
| TimeOnlyTypeHandler | java.util.Date | TIME类型 | 
| SqlTimestampTypeHandler | java.sql.Timestamp | TIMESTAMP类型 | 
| SqlDateTypeHandler | java.sql.Date | DATE类型 | 
| SqlTimeTypeHandler | java.sql.Time | TIME类型 | 
| ObjectTypeHandler | 任意 | 其他或未指定类型 | 
| EnumTypeHandler | Enumeration类型 | VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引) | 
3.5 mappers映射器
mappers:映射器,加载mapper文件。
3.5.1 单个加载映射文件
单个映射文件的加载:mapper。
-  resource: 从classpath下加载mapper文件 
<mappers>
    <!--
        <mapper>单个加载映射文件
        resource:通过相对路径加载文件(项目源目录下的文件)
        url:通过绝对路径加载文件(文件系统中文件)
    -->
    <mapper resource="mapper/DeptMapper.xml"/>
    <mapper resource="mapper/EmpMapper.xml"/>
</mappers>-  class: 配置dao接口的全限定名,通过Java中的dao接口的名称加载mapper.xml文件 
<mappers>
    <!--
        <mapper>单个加载映射文件
        class : 配置mapper接口的全限定名,通过Java中的Mapper接口来加载映射文件
    -->
    <mapper class="com.newcapec.mapper.DeptMapper"/>
    <mapper class="com.newcapec.mapper.EmpMapper"/>
</mappers>要求:
-  必须使用mapper代理的开发方式; 
-  mapper.xml文件的名称必须与dao接口的名称保持一致; 
-  mapper.xml文件必须与dao接口放在同一个目录下; 注意:同一个目录是指编译之后的目录,并非开发时的目录。 

3.5.2 批量加载映射文件
批量映射文件的加载:package。
-  name:dao接口与mapper文件存放的共同的目录名称 此种配置使mapper扫描指定包,并在此包下获取所有的接口以及与接口名称相同mapper文件,并加载; 
<mappers>
    <!--
        <package>批量加载映射文件
        name:存放Mapper接口与mapper.xml文件的包名
    -->
    <package name="com.newcapec.mapper"/>
</mappers>要求:与mapper接口加载单个映射文件(class方式)一致。
3.5.3 应用
实体类:
public class Emp {
    private Integer empno;
    private String ename;
    private String job;
    private Integer mgr;
    private Date hiredate;
    private Double sal;
    private Double comm;
    private Integer deptno;
    private String gender;
    public Integer getEmpno() {
        return empno;
    }
    public void setEmpno(Integer empno) {
        this.empno = empno;
    }
    public String getEname() {
        return ename;
    }
    public void setEname(String ename) {
        this.ename = ename;
    }
    public String getJob() {
        return job;
    }
    public void setJob(String job) {
        this.job = job;
    }
    public Integer getMgr() {
        return mgr;
    }
    public void setMgr(Integer mgr) {
        this.mgr = mgr;
    }
    public Date getHiredate() {
        return hiredate;
    }
    public void setHiredate(Date hiredate) {
        this.hiredate = hiredate;
    }
    public Double getSal() {
        return sal;
    }
    public void setSal(Double sal) {
        this.sal = sal;
    }
    public Double getComm() {
        return comm;
    }
    public void setComm(Double comm) {
        this.comm = comm;
    }
    public Integer getDeptno() {
        return deptno;
    }
    public void setDeptno(Integer deptno) {
        this.deptno = deptno;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    @Override
    public String toString() {
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", job='" + job + '\'' +
                ", mgr=" + mgr +
                ", hiredate=" + hiredate +
                ", sal=" + sal +
                ", comm=" + comm +
                ", deptno=" + deptno +
                ", gender='" + gender + '\'' +
                '}';
    }
}接口:
public interface EmpMapper {
    List<Emp> select();
}mapper文件:
<?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.newcapec.mapper.EmpMapper">
    <select id="select" resultType="Emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
    </select>
</mapper>测试:
/**
 * Mappers测试
 */
public class MappersTest {
    @Test
    public void testSelectEmp() {
        SqlSession sqlSession = MybatisUtil.getSession();
        EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> list = empMapper.select();
        for (Emp emp : list) {
            System.out.println(emp);
        }
        sqlSession.close();
    }
}3.6 Mybatis配置文件的标签顺序
Mybatis配置文件中各标签的位置顺序如下:
	properties?,
    settings?, 
    typeAliases?, 
    typeHandlers?, 
    objectFactory?, 
    objectWrapperFactory?, 
    reflectorFactory?, 
    plugins?, 
    environments?, 
    databaseIdProvider?, 
    mappers?
        
    具体可以参考 http://mybatis.org/dtd/mybatis-3-config.dtd 文件。









