话引

  • 前两张我们分别介绍了Mybatis环境搭建及其组件的生命周期。这些都是我们Mybatis入门必备技能。有了前两篇的铺垫我们今天就来深入下Mybatis, 也为了填下之前埋下的坑。

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=""/>
<!--设置-->
<settings/>
<!--定义别名-->
<typeAliases>
<package name=""/>
</typeAliases>
<!--类型处理器-->
<typeHandlers/>
<!--对象工厂-->
<objectFactory/>
<!--插件-->
<plugins/>
<!--定义数据库信息,默认使用development数据库构建环境-->
<environments default="development">
<environment id="development">
<!--jdbc事物管理-->
<transactionManager type="JDBC"/>
<!--配置数据库连接信息-->
<dataSource type="POOLED"/>
</environment>
</environments>
<!--数据库厂商标识-->
<databaseIdProvider/>
<mappers/>
</configuration>
  • 上面模板列出了所有xml可以配置的属性。这里plugins是一个让人哭笑不得的东西。用的好是利器,用的不好就是埋坑。接下来我们来看看各个属性的作用

properties

  • 该标签的作用就是引入变量。和maven的properties一样。在这里定义的变量或者引入的变量,在下面我们是可以童工${}使用的。

子标签property


<properties>
<property name="zxhtom" value="jdbc:mysql://localhost:3306/mybatis"/>
</properties> <dataSource type="POOLED">
<property name="driver" value="${zxhtom}"/>
<dataSource>
  • 上述的配置就可以直接使用zxhtom这个变量。

resource

  • 除了上述方法我们还可以通过引入其他properties文件,就可以使用文件里的配置变量了。

<properties resource="mybatis.properties"/>

程序注入

  • 最后还有一种我们在构建SqlSessionFactory的时候重新载入我们的Properties对象就可以了。另外三者的优先级是从低到高

settings


configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));
configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));
configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory")));
configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));
configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));
configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));
configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));
configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));
configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null));
configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));
configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));
configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));
configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));
configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));
configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));
configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));
configuration.setDefaultEnumTypeHandler(resolveClass(props.getProperty("defaultEnumTypeHandler")));
configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));
configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), true));
configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
configuration.setLogPrefix(props.getProperty("logPrefix"));
configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
  • 上面代码是我们在XMLConfigBuilder解析settings标签的代码。从这段代码中我们了解到settings子标签。
参数 功能 可选值 默认值
autoMappingBehavior 指定Mybatis应如何自动映射列到字段上。
NONE : 表示取消自动映射
PARTIAL:只会自动映射没有定义嵌套结果集映射的结果集
FULL : 自动映射任意复杂的结果集
NONE、PARTIAL、FULL PARTIAL
autoMappingUnknownColumnBehavior 指定识别到位置列或属性的时间
NONE : 什么都不做
WARNING:日志会报警(前提是日志设置了显示权限)
FAILING : 抛出异常。
NONE, WARNING, FAILING NONE
cacheEnabled 该配置影响的所有映射器中配置的缓存的全局开关 true|false true
proxyFactory 指定Mybatis创建具有延迟加载能力的对象所用到的代理工具未指定时将自动查找 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING not set
lazyLoadingEnabled 延时加载全局开关
开启时:级联对象会延时加载;级联标签中可以通过fetchType来定制覆盖此选项
true|false false
aggressiveLazyLoading 启用时:对任意延迟属性的调用会使带有延迟加载属性的对象分层性质完整加载,反之按需加载 true|false true
multipleResultSetsEnabled 是否允许单一语句返回多结果集 true|false true
useColumnLabel 确切的说当映射找不到参数时会使用列标签(数据库列名)代替别名去映射 true|false true
useGeneratedKeys 允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby) true|false false
defaultExecutorType 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新 SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout 设置超时时间,决定驱动等待数据库响应的秒数 整数 null
defaultFetchSize 设置数据库resultSet读取数据方式,默认全部加载进内存,设置该属性可以设置一次性读多少条数据进内存 整数 null
mapUnderscoreToCamelCase 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 true|false false
safeRowBoundsEnabled -允许在嵌套语句中使用分页 true|false false
localCacheScope 一级缓存。mybatis默认对同一个sqlsession中数据是共享的。一个sqlsession调用两次相同查询实际只会查询一次。就是因为该属性为SESSION , STATEMENT则针对的是每一条sql SESSION|STATEMENT SESSION
jdbcTypeForNull 当没有为参数提供特定的jdbc类型时,为空值则指定JDBC类型。在新增时我们没有设置参数,这个时候就会根据此参数天长。加入设置VARCHAR,那么我们新增的数据没传参数则为空字符 NULL|VARCHAR|OTHER OTHER
lazyLoadTriggerMethods 指定具体方法延时加载 方法 equals,clone,hashCode,toString
safeResultHandlerEnabled 允许在嵌套语句中使用分页 true|false true
defaultScriptingLanguage 动态SQL生成的默认语言 org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver
defaultEnumTypeHandler mybatis默认的枚举处理类
callSettersOnNulls 指定当结果集中值为null的时候是否调用映射对象的setter(put)方法。
useActualParamName 允许使用他们的编译后名称来映射,3.4.2后默认true.在xml中#{0}则报错。设置为false,则#{0}代表第一个参数#{n}第n个 true|false true
returnInstanceForEmptyRow 当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集 (如集合或关联)。(新增于 3.4.2) true|false false
logPrefix 指定 MyBatis 增加到日志名称的前缀。

别名

  • 别名是mybatis为我们项目中类起的一个名字,类名往往会很长所以别名就方便我们平时的开发。Mybatis为我们内置了一些类的别名:byte、short、int、long、float、double、boolean、char等基础类型的别名。还有其的封装类型、String,Object,Map,List等等常用的类。

    org.apache.ibatis.type.TypeAliasRegistry这个类中帮我们内置了别名。可以看下。自定义别名也是通过这个类进行注册的。我们可以通过settings中typeAliases配置的方式结合@Alias。或者扫描包也可以的。

TypeHandler

  • 这个接口就四个方法

public interface TypeHandler<T> { /**
* 设置参数是用到的方法
*/
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException; T getResult(ResultSet rs, String columnName) throws SQLException; T getResult(ResultSet rs, int columnIndex) throws SQLException; T getResult(CallableStatement cs, int columnIndex) throws SQLException; }
  • 可以理解成拦截器。它主要拦截的是设置参数和获取结果的两个节点。这个类的作用就是将Java对象和jdbcType进行相互转换的一个功能。同样的在org.apache.ibatis.type.TypeHandlerRegistry这个类中mybatis为我们提供了内置的TypeHandler。基本上是对于基本数据和分装对象的转换。
  • 下面我们随便看一个TypeHandler处理细节
public class BooleanTypeHandler extends BaseTypeHandler<Boolean> {

  @Override
public void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType)
throws SQLException {
ps.setBoolean(i, parameter);
} @Override
public Boolean getNullableResult(ResultSet rs, String columnName)
throws SQLException {
boolean result = rs.getBoolean(columnName);
return !result && rs.wasNull() ? null : result;
} @Override
public Boolean getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
boolean result = rs.getBoolean(columnIndex);
return !result && rs.wasNull() ? null : result;
} @Override
public Boolean getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
boolean result = cs.getBoolean(columnIndex);
return !result && cs.wasNull() ? null : result;
}
}
  • setParameter是PreparedStatement进行设置成boolean类型。getResult分别通过三种不同方式获取。在这些方法里我们可以根据自己也无需求进行控制。常见的控制是枚举的转换。传递参数过程可能是枚举的name,但是传递到数据库中要枚举的index.这种需求我们就可以在TypeHandler中实现。我们书写的typeHandler之后并不能被识别,还需要我们在resultMap中的result标签中通过typeHandler指定我们的自定义Handler.

自定义TypeHandler

  • 承接上文我们说道枚举的转换。下面我们还是已学生类为例。学生中性别之前是boolean类型。现在我们采用枚举类型。但是数据库中存的还是数据,01.

EnumTypeHandler

  • 在TypeHandlerRegister类中申明了默认的枚举类处理器是private Class<? extends TypeHandler> defaultEnumTypeHandler = EnumTypeHandler.class;
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
String s = rs.getString(columnName);
return s == null ? null : Enum.valueOf(type, s);
}
  • 我们通过这个方法可以看出,这个枚举处理器适合已枚举名称存储的方式





EnumOrdinalTypeHandler

  • 在Enum中还有一个属性oridinal。这个表示枚举中的索引。然后我们通过查看Mybatis提供的处理器发现有个叫EnumOrdinalTypeHandler。我们很容易联想到的就是这个处理器是通过枚举的所以作为数据库内容的。在SexEnum中MALE存储到数据库中则为0.注意这个0不是我们的index.而是MALE的索引。如果将MALE和FEMAEL调换。那么MALE索引则为1.

  • 因为默认的是EnumTypeHandler。所以想用EnumOrdinalTypeHandler的话我们要么在resultMap中sex字段指定该处理器。要不就通过配置文件typeHandlers注册进来。(将处理器与Java类进行绑定。mybatis遇到这个Java对象的时候就知道用什么处理器处理)


<typeHandlers>
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.github.zxhtom.enums.SexEnum"/>
</typeHandlers>

SexTypeHandler

  • 上面的不管是通过名称存储还是通过索引存储都不太满足我们的需求。我们想通过我们的index存储。那么这时候我们就得自定义处理逻辑了。Mybatis处理器都是继承BaseTypeHandler。因为BaseTypeHandler实现了TypeHandler.所以我们这里也就继承BaseTypeHandler。

public class SexTypeHandler extends BaseTypeHandler<SexEnum> { @Override
public void setNonNullParameter(PreparedStatement ps, int i, SexEnum parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i,parameter.getIndex());
} @Override
public SexEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
int i = rs.getInt(columnName);
return SexEnum.getSexEnum(i);
} @Override
public SexEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
int i = rs.getInt(columnIndex);
return SexEnum.getSexEnum(i);
} @Override
public SexEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
int i = cs.getInt(columnIndex);
return SexEnum.getSexEnum(i);
}
}

typeHandler注意点

  • 在编写自定义处理器的时候我们得之处Javatype、jdbctype。两者不是必填。但至少得有一个。正常我们默认javatype是必填的。
  • 填写的方式有三种
    • 通过MappedTypes、MappedJdbcTypes分别指定javatype、jdbctype
    • 通过在mybatis-config.xml中配置typeHandlers进行注解。里面也有这两个属性的配置。
    • 通过在mapper.xml的resultmap中再次指定某个字段的typehandler.
  • TypeHandler为我们提供了Java到jdbc数据的转换桥梁。极大的方便了我们平时的开发。让我们开发期间忽略数据的转换这么糟心的事情。

加入战队

# 加入战队

微信公众号

mybatis精讲(三)--标签及TypeHandler使用的更多相关文章

  1. mybatis精讲(五)--映射器组件

    目录 前言 标签 select insert|update|delete 参数 resultMap cache 自定义缓存 # 加入战队 微信公众号 前言 映射器之前我们已经提到了,是mybatis特 ...

  2. Mybatis精讲(一)---环境配置及架构梳理

    目录 简介 ORM模型 Hibernate Ibatis 环境搭建 jar 配置 xml方式配置 代码方式配置 两种方式对比 Mybatis结构 源码解读xml环境加载 映射器解读 Ibatis # ...

  3. Mybatis精讲(二)---生命周期

    目录 回顾 SqlSessionFactoryBuilder SqlSessionFactory openSessionFromDataSource Executor SqlSession Mappe ...

  4. mybatis精讲(四)--ObjectFactory

    目录 前言 mybatis的ObjectFactory 源码 setProperties create instantiateClass 使用场景 # 加入战队 微信公众号 前言 ObjectFact ...

  5. mybatis精讲(六)--二级缓存

    目录 简介 配置 源码 CachingExecutor 自定义二级缓存 # 加入战队 微信公众号 简介 上一章节我们简单了解了二级缓存的配置.今天我们详细分析下二级缓存以及为什么不建议使用二级缓存. ...

  6. mybatis精讲(七)--动态sql

    目录 常用标签 if元素 choose元素 trim元素 forearch bind元素 在我们传统的开发中我们会通过拼接sql达到数据库的操作.java中的拼接不仅效率低下而且代码很长不易维护.而M ...

  7. 第三百七十节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索结果分页

    第三百七十节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索结果分页 逻辑处理函数 计算搜索耗时 在开始搜索前:start_time ...

  8. 第三百六十九节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索功能

    第三百六十九节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索功能 Django实现搜索功能 1.在Django配置搜索结果页的路由映 ...

  9. 第三百六十七节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)scrapy写入数据到elasticsearch中

    第三百六十七节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)scrapy写入数据到elasticsearch中 前面我们讲到的elasticsearch( ...

随机推荐

  1. vue入门笔记(新手入门必看)

    一.什么是Vue? 1.    vue为我们提供了构建用户界面的渐进式框架,让我们不再去操作dom元素,直接对数据进行操作,让程序员不再浪费时间和精力在操作dom元素上,解放了双手,程序员只需要关心业 ...

  2. ASP.NET Core中的配置

    配置 参考文件点击跳转 配置来源 命令行参数 自定义提供程序 目录文件 环境变量 内存中的.NET 对象 文件 默认配置 CreateDefaultBuilder方法提供有默认配置,在这个方法中会接收 ...

  3. Leetcode Tags(2)Array

    一.448. Find All Numbers Disappeared in an Array 给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了 ...

  4. python之ORM(对象关系映射)

    实现了数据模型与数据库的解耦,通过简单的配置就可以轻松更换数据库,而不需要更改代码.orm操作本质上会根据对接的数据库引擎,翻译成对应的sql语句.所有使用Django开发的项目无需关心程序底层使用的 ...

  5. 小白 Python 爬虫部署 Linux

    前言 前面国庆节的时候写过一个简易的爬虫. <Python 简易爬虫实战> 还没看过的同学可以先看一下,这只爬虫主要用来爬取各个博客平台的阅读量等数据,一直以来都是每天晚上我自己手动在本地 ...

  6. Ubuntu编译安装nginx以及配置自动启动

    本文主要介绍ubuntu如何编译安装nginx以及遇到的问题 和 配置系统自动启动服务 查看操作系统版本 cat /etc/issue  Ubuntu 18.04.3 LTS \n \l    更改镜 ...

  7. http和Https简介、详解

    目录 引用 一.HTTP和HTTPS的基本概念 二.HTTP与HTTPS有什么区别? 三.HTTPS的工作原理 四.HTTPS的优点 五.HTTPS的缺点 六.http切换到HTTPS 引用 超文本传 ...

  8. 微软的分布式应用框架 Dapr Helloworld

    Dapr HelloWorld Dapr Distributed Application Runtime. An event-driven, portable runtime for building ...

  9. c#中关于string的特性介绍以及注意事项

    前言 string类型在我们实际项目开发中是一个最使用的类型,string是一个引用类型这一点大家都知道,但是在实际使用过程中,大家会发现string和我们常见的引用类型使用还真不一样,看下面的一个简 ...

  10. Pandas 转换连接

    # 导入相关库 import numpy as np import pandas as pd 拼接 有两个 DataFrame,都存储了用户的一些信息,现在要拼接起来,组成一个 DataFrame. ...