MyBatis学习记录02——配置

###0.前言
记录MyBatis的配置以及对应的说明

《Java EE互联网轻量级框架整合开发——SSM框架(Spring MVC+Spring+MyBatis)和Redis实现》

MyBatis配置元素:

<configuration> //配置
    <properties />    //属性
    <settings />    //设置
    <typeAliases />    //别名
    <typeHandlers />    //类型处理器
    <objectFactory />    //对象工厂
    <plugins />            //插件
    <environments>        //环境配置
        <environment>    //环境变量        
            <transactionManaager /> //事务管理器
            <dataSource />            //数据源
        </environment>
    </environments>
    <databaseIdProvider />     //数据库标识
    <mappers />             //映射器
</configuration>

###1.配置节点说明

  • configuration:配置顶级节点
  • properties:配置运行参数(xml的上下文使用)
    • MyBaits的properties节点中(property子元素)
    • 外置properties文件
    • 代码传入
  • settings:MyBatis全局设置
  • typeAliases:别名设置,主要是简写类的全限定名称。不区分大小写
  • typeHandlers:类型转换器,javaType <=> typeHandler <=> jdbcType(java类型和数据库类型之间的转化)
  • objectFactory:对象工厂,创建结果集实例
  • plugins:插件
  • environments:运行环境配置,配置数据库信息
    • environment:单个环境配置实例
    • transactionManaager:事务管理器(JDBC、MANAGED)
    • dataSource:数据源配置,配置数据库连接策略(POOLED、UNPOOLED、JNDI),连接参数(驱动、url、用户名和密码等)
  • databaseIdProvider:数据库标识,多数据库兼容
  • mappers:映射器,维护SQL语句,并返回SQL执行后的java对象的结果集。

###2.properties 属性
属性主要是给系统配置一些运行参数,可以放在外部配置文件中,以便参数的修改而不会引起代码的重新编译。

  • MyBaits的properties节点中(property子元素)

    //mybatis-config.xml
    <configuration>
    <properties>
        <property name="database.driver" value="com.mysql.jdbc.Driver"/> 
        <property name="database.url" value="jdbc:mysql://localhost:3306/ssm"/> 
        <property name="database.username" value="root"/> 
        <property name="database.password" value="root"/>
        </properties>
    //...省略...
    <!-- 数据库环境 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="com.learn.ssm.chapter4.datasource.DbcpDataSourceFactory">
                <property name="driver" value="${database.driver}" />
                <property name="url" value="${database.url}" />
                <property name="username" value="${database.username}" />
                <property name="password" value="${database.password}" />
            </dataSource>
        </environment>
    </environments>
    //...省略...
    </configuration>
    
  • 外置properties文件

    //jdbc.properties文件
    database.driver=com.mysql.jdbc.Driver
    database.url=jdbc:mysql://localhost:3306/ssm
    database.username=root
    database.password=root
    
    //mybatis-config.xml
    <configuration>
    <properties resource="jdbc.properties"/>
    //...省略...
    <!-- 数据库环境 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="com.learn.ssm.chapter4.datasource.DbcpDataSourceFactory">
                <property name="driver" value="${database.driver}" />
                <property name="url" value="${database.url}" />
                <property name="username" value="${database.username}" />
                <property name="password" value="${database.password}" />
            </dataSource>
        </environment>
    </environments>
    //...省略...
    </configuration>
    
  • 代码传入

    //SqlSessionFactory创建传入,此例子为动态解密数据库用户名和密码
    InputStream in = Resources.getResourceAsStream("jdbc.properties");
    Properties props = new Properties();
    props.load(in);
    String username = props.getProperty("database.username");
    String password = props.getProperty("database.password");
    // 解密用户和密码,并在属性中重置
    props.put("database.username", CodeUtils.decode(username));
    props.put("database.password", CodeUtils.decode(password));
    inputStream = Resources.getResourceAsStream(resource);
    // 使用程序传递的方式覆盖原有的properties属性参数
    sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, props);
    

配置优先级:
代码配置 > properties文件 > property子元素

###3.settings 设置
全量配置样例:

<settings>
<setting name="cacheEnabled" value="true" /> <!--映射器缓存开启 -->
<setting name="lazyLoadingEnabled" value="true" /> <!--延时加载开启 -->
<setting name="multipelResultSetsEnabled" value="true" /> <!--单一语句返回多结果集,需兼容驱动 -->
<setting name="useColumnLabel" value="true" /> <!--使用列标签代替列名 -->
<setting name="useGeneratedKeys" value="false" /> <!--允许JDBC自动生成主键,需要驱动兼容 -->
<setting name="autoMappingBehavior" value="PARTIAL" /> <!--指定自动映射行为(NONE、PARTIAL、FULL) -->
<setting name="autoMappingUnknownColumnBehavior" value="WARNING" /> <!--自动映射未知列的行为,WARNING以上有日志 -->
<setting name="defaultExecutorType" value="SIMPLE" /> <!--执行器(SIMPLE、REUSE、BATCH) -->
<setting name="defaultStatementTimeout" value="25" /> <!--驱动等待数据库响应的超时时间 -->
<setting name="defaultFetchSize" value="100" /> <!--数据库驱动默认返回条数限制 -->
<setting name="safeRowBoundsEnabled" value="false" /> <!--允许嵌套语句中使用分页,允许为false -->
<setting name="mapUnderscoreToCamelCase" value="false" /> <!--数据库A_COLUMN自动转java中的驼峰aColumn -->
<setting name="localCacheScope" value="SESSION" /> <!--缓存查询(SESSION、STATEMENT) -->
<setting name="jdbcTypeForNull" value="OTHER" /> <!--为空值指定jdbc类型(OTHER、NULL、VARCHAR)-->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString" /> <!--指定触发延时加载的方法 -->
</settings>

部分设置属性说明:

  • autoMappingBehavior:指定自动映射行为(resultMap、association、collection中的autoMapping可覆盖)
    • NONE:取消自动映射
    • PARTIAL:只会自动映射没有定义嵌套结果集映射的结果集(如果没有显式定义result标签,不会帮你把结果映射到pojo上)。<默认值>
    • FULL:自定映射任意复杂结果集
  • autoMappingUnknownColumnBehavior:自动映射未知列时的行为
    • NONE:不处理。 <默认值>
    • WARNING:显示相关日志
    • FAILING:抛出异常SqlSessionException
  • defaultExecutorType:默认执行器
    • SIMPLE:普通执行器,每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。 <默认值>
    • REUSE:重用预处理执行器,执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map<String, Statement>内,供下一次使用。简言之,就是重复使用Statement对象。
    • BATCH:重用语句并执行批量更新。执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
  • localCacheScope:利用本地缓存机制防止循环引用和加速重复嵌套查询
    • SESSION:会话作用域。<默认值>
    • STATEMENT:语句作用域。
  • jdbcTypeForNull:当没有为参数提供特定的JDBC类型时,为空值指定JDBC类型。
    • NULL
    • VARCHAR
    • OTHER:<默认值>

缓存相关问题(cacheEnabled和localCacheScope的设置问题):
MyBatis缓存
MyBatis 缓存机制深度解剖 / 自定义二级缓存

jdbcType对照表

JdbcType MySql Oracle JavaType
ARRAY Array
BIGINT BIGINT long
BINARY BINARY byte[]
BIT BIT BIT boolean
CLOB CLOB CLOB Clob
BLOB BLOB BLOB Blob
BOOLEAN boolean
CHAR CHAR CHAR String
DATE DATE DATE java.sql.Date
DECIMAL DECIMAL DECIMAL java.math.BigDecimal
DOUBLE DOUBLE NUMBER double
FLOAT FLOAT FLOAT double
INTEGER INTEGER INTEGER int
LONGVARBINARY byte[]
LONGVARCHAR VARCHAR LONG String
NCHAR NCHAR String
NCLOB NCLOB
NULL
NUMERIC NUMERIC NUMERIC/NUMBER java.math.BigDecimal
NVARCHAR
OTHER ANY
REAL REAL REAL float
SMALLINT SMALLINT SMALLINT short
STRUCT Struct
TIME TIME TIME java.sql.Time
TIMESTAMP TIMESTAMP/DATETIME TIMESTAMP java.sql.Timestamp
TINYINT TINYINT TINYINT byte
UNDEFINED
VARBINARY VARBINARY byte[]
VARCHAR VARCHAR VARCHAR String
DATALINK java.net.URL[color=red][/color]
REF Ref
DISTINCT mapping of underlying type

记录原文地址:
mybatis的jdbcType和javaType、oracle,MySQL的对应类型

###4.typeAliases 别名设置
通过简写来代替类名,有TypeAliasRegistry定义。

注意:

  1. 别名不区分大小写。
  2. 系统定义的别名中,数组和Map类型基本不支持数组(即后面加[]声明为数组)

别名的使用:

方法一:

<typeAliases><!-- 别名:单个声明 -->
    <typeAlias alias="role" type="com.nowy.mybatissample.pojo.Role"/>
</typeAliases>

方法二:

<typeAliases><!-- 别名:整个包扫描 -->
    <package name="com.nowy.mybatissample.pojo" />
</typeAliases>

其中整个包扫描定义的别名规则为: Role => role
可以通过类名上方的注解(@Alias(“name”))重命名

例如:

@Alias("role")
public class Role {
    //...
}

###5.typeHnadler 类型转化器

  • 主要作用是java类型与jdbc类型的相互转化处理。
  • MyBatis会自动探测匹配类型,大部分情况下默认提供的typeHandler已经足够使用。
  • 但在类似枚举类型时候需要自定义typeHandler处理转换。

事例:

//SexEnumTypeHandler类
public class SexEnumTypeHandler implements TypeHandler<SexEnum> {

    @Override
    public void setParameter(PreparedStatement ps, int i, SexEnum parameter,
            JdbcType jdbcType) throws SQLException {
        ps.setInt(i, parameter.getId());
    }

    @Override
    public SexEnum getResult(ResultSet rs, String columnName)
            throws SQLException {
        int id = rs.getInt(columnName);
        return SexEnum.getSexById(id);
    }

    @Override
   public SexEnum getResult(ResultSet rs, int columnIndex) throws SQLException {
        int id = rs.getInt(columnIndex);
        return SexEnum.getSexById(id);
    }

    @Override
    public SexEnum getResult(CallableStatement cs, int columnIndex)
            throws SQLException {
        int id = cs.getInt(columnIndex);
        return SexEnum.getSexById(id);
    }

}

配置文件注册:

<typeHandlers>

    <!--方式一:单个注册-->
    <typeHandler jdbcType="VARCHAR" javaType="string"  handler="com.nowy.mybatissample.typehandler.MyTypeHandler" 
        />

    <!--方式二:包名扫描-->
    <package name="com.nowy.mybatissample.typehandler" />
</typeHandlers>

Mapper中结果集引用:

<resultMap id="userMapper" type="user"> 
    <!--方式一,类型匹配-->
    <result property="name" column="name" jdbcType="VARCHAR" javaType="string"/> 

    <!--方式二,直接指定typeHandler-->
    <result property="sex" column="sex"  
       typeHandler="com.nowy.mybatissample.typehandler.SexEnumTypeHandler"/>
</resultMap>    

使用包扫描注册typeHandler,可以通过注解配置javaType和jdbcType的匹配规则

//启用扫描注册的时候需要注解
@MappedTypes(String.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class MyTypeHandler implements TypeHandler<String> {
    //...
}

###6.environments 环境配置
主要配置数据库的连接策略和数据库连接的各种参数

  • environment:单个环境配置实例
  • transactionManaager:事务管理器
    • JDBC:以JDBC的方式进行数据库的提交和回滚操作
    • MANAGED:把事务交给容器处理,提交和回滚不做任何操作
  • dataSource:数据源配置,
    • 配置数据库连接策略(POOLED(连接池)、UNPOOLED(非连接池)、JNDI(JNDI上下文))
    • 连接参数(驱动、url、用户名和密码等)

###7.databaseIdProvider 数据库厂商标识
主要作用是支持多个数据库厂商进行开发,用于指定SQL执行在哪个数据库中,对应Mapper中的sql语句的databaseId属性,当databaseId被设置,系统会优先获取与数据库配置一致的SQL,如果没有,则获取没有设置databaseId的默认语句。如果最后还是获取不到,则抛出异常。

<databaseIdProvider type="DB_VENDOR">
    <property name="Oracle" value="oracle" />
    <property name="MySQL" value="mysql" />
    <property name="DB2" value="db2" />
</databaseIdProvider>

###8.ObjectFactory 对象工厂
MyBatis通过对象工厂完成结果集的创建(DefaultObjectFactory)。可以通过自定义objectFactory对返回结果集进行监听。

###9.总结
本文主要对MyBatis的学习进行记录和归纳,以便使用时的快速回忆。学习的书本为《Java EE互联网轻量级框架整合开发——SSM框架(Spring MVC+Spring+MyBatis)和Redis实现》,同时对不理解的知识点进行了进一步的查找和学习。

Mapper将会进行单独记录。

END

–Nowy

– 2018.12.04

分享到