导图社区 【MyBaits】MyBaits从入门到精通
从一个简单的MyBatis查询入手,讲解了在MyBatis XML方式和注解方式中进行增、删、改、查操作的基本用法,介绍了动态SQL在不同方面的应用以及在使用过程中的最佳实践方案。
编辑于2021-01-31 19:48:21MyBaits从入门到精通
1.MyBatis入门
MyBatis 简介
前身是 iBATIS MyBatis 是一款优秀的支持自定义 SQL 查询、存储过程和高级映射的持久层框架,消除了几乎所有的 JDBC 代码和参数的手动设置以及结果集的检索 。 MyBatis 可以使用 XML 或注解进行配置和映射, MyBatis 通过将参数映射到配置的 SQL 形成最终执行的 SQL 语句 ,最后将执行SQL 的结果映射成 Java 对象返回。 mybatis-3 ( https://github.com/mybatis/mybatis-3 ): MyBatis 源码,也是本书中主要讲解和使用的内容 。 generator ( https ://github.com/mybatis/generator ) : 代码生成器,可以生成一些常见的基本方法,提高工作效率。 ehcache-cache( https://github.com/mybatis/ehcache-cache ):默认集成 Ehcache 的缓存实现 。 redis-cache ( htφs ://github.com/mybatis/redis-cache ) : 默认集成 Redi s 的缓存实现 。 spring (https://github.com/mybatis/spring ) : 方便和 Spring 集成的工具类 。 mybatis-spring-boot ( https://github .com/mybatis/mybatis-spring-boot ):方便和 Spring Boot 集成的工具类。
创建Maven项目
在pom文件中添加相关依赖
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 tk.mybatis simple 0.0.1-SNAPSHOT 1.6 UTF-8 junit junit 4.12 test org.mybatis mybatis 3.3.0 mysql mysql-connector-java 5.1.38 org.slf4j slf4j-api 1.7.12 org.slf4j slf4j-log4j12 1.7.12 log4j log4j 1.2.17 maven-compiler-plugin ${java.version} ${java.version}
简单配置
准备数据库
建库,建表,添加数据
配置MyBaits
XML配置
myBaits-config.xml文件 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
创建实体类和Mapper.xml文件
CountryMapper.xml "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > select id,countryname,countrycode from country
配置 Log4j 以便查看 MyBatis 操作数据库的过程
log4j.properties #全局配置 log4j.rootLogger=ERROR, stdout #MyBatis 日志配置 log4j.logger.tk.mybatis.simple.mapper=TRACE #控制台输入配置 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
编写测试代码让 MyBatis 跑起来
2.MyBatis XML 方式的基本用法
权限控制需求
RBAC (Role-Based Access Control,基于角色的访问控制)方式。
RBAC
创建实体类
mybatis:下画线转驼峰命名; 在实体类中不要使用基本类型 ;
使用 XML 方式
强大之处在于映射语句; 接口可以配合XML使用,也可以配合注解来使用。XML可以单独使用,但是注解必须在接口中使用。
select 用法
select r.id, r.role_name roleName, r.enabled, r.create_by createBy, r.create_time createTime, u.user_name as "user.userName", u.user_email as "user.userEmail" from sys_user u inner join sys_user_role ur on u.id = ur.user_id inner join sys_role r on ur.role_id = r.id where u.id = #{userId}
接口与XML文件关联
1、接口中方法和XML又是怎么关联的呢? XML中的select标签的id属性值和定义的接口方法名是一样的。
标签和属性
#{id}:MyBatisSQL中使用预编译参数的一种方式,大括号中的id是传入的参数名。
resultMap
resultMap:用于设置返回值的类型和映射关系。 resultMap标签用于配置Java对象的属性和查询结果列的对应关系,通过resultMap中配置的column和property可以将查询列的值映射到type对象的属性上。 resultMap包含的所有属性: id:必填,并且唯一。在select标签中,resultMap指定的值即为此处id所设置的值。 type:必填,用于配置查询列所映射到的Java对象类型。 extends:选填,可以配置当前的resultMap继承自其他的resultMap,属性值为继承resultMap的id。 autoMapping:选填,可选值为true或false,用于配置是否启用非映射字段(没有在resultMap中配置的字段〉的自动映射功能,该配置可以覆盖全局的autoMappingBehavior配置。 resultMap包含的所有标签: constructor:配置使用构造方法注入结果,包含以下两个子标签。 idArg:id参数,标记结果作为id(唯一值),可以帮助提高整体性能。 arg:注入到构造方法的一个普通结果。 id:一个id结果,标记结果作为id(唯一值),可以帮助提高整体性能。 result:注入到Java对象属性的普通结果。 association:一个复杂的类型关联,许多结果将包成这种类型。 collection:复杂类型的集合。 discriminator:根据结果值来决定使用哪个结果映射。 case:基于某些值的结果映射。
id
接着来看一下id和result标签包含的属性: column:从数据库中得到的列名,或者是列的别名。 property:映射到列结果的属性。可以映射简单的如“username”这样的属性,也可以映射一些复杂对象中的属性,例如 “address.street.number”,这会通过“.”方式的属性嵌套赋值。 javaType:一个Java类的完全限定名,或一个类型别名(通过typeAlias配置或者默认的类型)。如果映射到一个 JavaBean,MyBatis通常可以自动判断属性的类型。如果映射到HashMap,则需要明确地指定javaType属性。 jdbcType:列对应的数据库类型。JDBC类型仅仅需要对插入、更新、删除操作可能为空的列进行处理。这是JDBCjdbcType的需要,而不是MyBatis的需要。 typeHandler:使用这个属性可以覆盖默认的类型处理器。这个属性值是类的完全限定名或类型别名。
result
关系
constructor:通过构造方法注入属性的结果值。构造方法中的idArg、arg参数分别对应着resultMap中的id、result标签,它们的含义相同,只是注入方式不同。resultMap中的id和result标签包含的属性相同,不同的地方在于,id代表的是主键(或唯一值)的字段(可以有多个),它们的属性值是通过setter方法注入的。
名称映射规则
property属性或别名委和对象中属性的名字相同,匹配时,MyBatis会先将两者都转换为大写形式,然后再判断是否相同。 因此在设直property属性或别名的时候,不需要考虑大小写是否一致。 提供 了 一个全局属性mapUnderscoreToCamelCase ,通过配置这个属性为 true 可以自动将以下画线方式命名的数据库列映射到 Java 对象的驼峰式命名属性中。
insert 用法
insert into sys_user( user_name, user_password, user_email, user_info, head_img, create_time) values( #{userName}, #{userPassword}, #{userEmail}, #{userInfo}, #{headImg, jdbcType=BLOB}, #{createTime, jdbcType=TIMESTAMP}) BLOB对应的类型是ByteArrayinputStream,就是二进制数据流; 由于数据库区分date、time、datetime类型,但是Java中一般都使用java.util.Date类型。因此为了保证数据类型的正确,需要手动指定日期类型,date、time、datetime对应的JDBC类型分别为 DATE、 TIME、 TIMESTAMP。
insert标签
id:命名空间中的唯一标识符,可用来代表这条语句。 parameterType:即将传入的语句参数的完全限定类名或别名。这个属性是可边的,因为MyBatis可以推断出传入语句的具体参数,因此不建议配置该属性。 flushCache:默认值为true,任何时候只要语句被调用,都会清空一级缓存和二级缓存。 timeout:设置在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。 statementType:对于STATEMENT、PREPARED、CALLABLE,MyBatis会分别使用对应的Statement、PreparedStatement、CallableStatement,默认值为PREPARED。 useGeneratedKeys:默认值为false。如果设置为true,MyBatis会使用JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键。 keyProperty:MyBatis通过getGeneratedKeys获取主键值后将要赋值的属性名。如果希望得到多个数据库自动生成的列,属性值也可以是以逗号分隔的属性名称列表。 keyColumn:仅对时SERT和UPDATE有用。通过生成的键值设置表中的列名,这个设置仅在某些数据库(如PostgreSQL)中是必须的,当主键列不是表中的第一列时需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 databaseId:如果配置了databaseidProvider(4.6节有详细配置方法),MyBatis会加载所有的不带databaseid的或匹配当前databaseid的语句。如果同时存在带databaseid和不带databaseid的语句,后者会被忽略。
使用 JDBC 方式返回主键自增的值
useGeneratedKeys="true"keyProperty="id" useGeneratedKeys设置为true后,MyBatis会使用JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键。获得主键值后将其赋值给keyProperty配置的id属性。
使用 selectKey 返回主键的值
SELECT LAST_INSERT_ID() resu ltT ype 用于设置返回值类型 。 order 属性的设置和使用的数据库有关 。 在 MySQL 数据库中, order 属性设置的值是 AFTER,因为当前记录的主键值在 insert 语句执行成功后才能获取到 。 而在 Oracle 数据库中, order 的值要设置为 BEFORE ,这是因为 Oracle中需要先从序列获取值,然后将值作为主键插入到数据库中 。
update 用法
update sys_user set user_name = #{userName}, user_password = #{userPassword}, user_email = #{userEmail}, user_info = #{userInfo}, head_img = #{headImg, jdbcType=BLOB}, create_time = #{createTime, jdbcType=TIMESTAMP} where id = #{id}
delete 用法
delete from sys_user where id = #{id}
多个接口参数的用法
/** * 根据用户 id 和 角色的 enabled 状态获取用户的角色 * * @param userId * @param enabled * @return */ List selectRolesByUserIdAndRoleEnabled(@Param("userId") Long userId, @Param("enabled") Integer enabled);
Mapper 接口动态代理实现原理
3.MyBaits注解方式的基本用法
MyBatis注解方式就是将SQL语句直接写在接口上。 优点是,对于需求比较简单的系统,效率较高。 缺点是,当SQL有变化时都需要重新编译代码,一般情况下不建议使用注解方式。
@Select 注解
@Select({"select id,role_name roleName, enabled, create_by createBy, create_time createTime", "from sys_role", "where id = #{id}"}) SysRole selectById(Long id);
使用 mapUnderscoreToCamelCase 配置
使用 resultMap 方式
@Results(id = "roleResultMap", value = { @Result(property = "id", column = "id", id = true), @Result(property = "roleName", column = "role_name"), @Result(property = "enabled", column = "enabled"), @Result(property = "createBy", column = "create_by"), @Result(property = "createTime", column = "create_time") }) @Select("select id,role_name, enabled, create_by, create_time from sys_role where id = #{id}") SysRole selectById2(Long id); 两个方法的区别是,后者的 SQL 中没有别名,需要通过@ Resu l t 注解配置映射。 @ResultMap("roleResultMap") @Select("select * from sys_role") List selectAll();
@Insert 注解
不需要返回主键
@Insert({"insert into sys_role(id, role_name, enabled, create_by, create_time)", "values(#{id}, #{roleName}, #{enabled}, #{createBy}, #{createTime, jdbcType=TIMESTAMP})"}) int insert(SysRole sysRole);
返回自增主键
@Insert({"insert into sys_role(role_name, enabled, create_by, create_time)", "values(#{roleName}, #{enabled}, #{createBy}, #{createTime, jdbcType=TIMESTAMP})"}) @Options(useGeneratedKeys = true, keyProperty = "id") int insert2(SysRole sysRole);
返回非自增主键
@Insert({"insert into sys_role(role_name, enabled, create_by, create_time)", "values(#{roleName}, #{enabled}, #{createBy}, #{createTime, jdbcType=TIMESTAMP})"}) @SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "id", resultType = Long.class, before = false) int insert3(SysRole sysRole);
@Update 注解和@Delete 注解
@Update({"update sys_role", "set role_name = #{roleName},", "enabled = #{enabled},", "create_by = #{createBy},", "create_time = #{createTime, jdbcType=TIMESTAMP}", "where id = #{id}" }) int updateById(SysRole sysRole); ------------------------------------------------------------------------ @Delete("delete from sys_role where id = #{id}") int deleteById(Long id);
Provider 注解
Provider 的注解中提供了两个必填属性 type 和 method 。 type 配置的是一个包含 method属性指定方法的类,这个类必须有空的构造方法,这个方法的值就是要执行的 SQL 语句, 并且method 属性指定的方法的返回值必须是 String 类型 。 @SelectProvider(type = PrivilegeProvider.class, method = "selectById") SysPrivilege selectById(Long id); public String selectById(final Long id) { return new SQL() { { SELECT("id, privilege_name, privilege_url"); FROM("sys_privilege"); WHERE("id = #{id}"); } }.toString(); }
4.Mybatis动态SQL
OGNL ( Object-Graph Navigation Language )表达式语言
if 用法
在 WHERE 条件中使用 if
select id, user_name userName, user_password userPassword, user_email userEmail, user_info userInfo, head_img headImg, create_time createTime from sys_user where 1=1 and user_name like concat('%', #{userName}, '%') and user_email = #{userEmail}
在 UPDATE 更新列中使用 if
update sys_user set user_name = #{userName}, user_password = #{userPassword}, user_email = #{userEmail}, user_info = #{userInfo}, head_img = #{headImg, jdbcType=BLOB}, create_time = #{createTime, jdbcType=TIMESTAMP}, id = #{id}, where id = #{id} 注意: 每个 if 元素里面 SQL 语句后面的逗号; 第二点就是 where 关键宇前面的 id=#{id }这个条件
在 INSERT 动态插入列中使用 if
insert into sys_user( user_name, user_password, user_email, user_info, head_img, create_time) values( #{userName}, #{userPassword}, #{userEmail}, #{userInfo}, #{headImg, jdbcType=BLOB}, #{createTime, jdbcType=TIMESTAMP})
choose 用法
choose 元素中包含 where和 otherwise 两个标签,一个 choose 中至少有一个 when ,有 0 个或者1个otherwise。 select id, user_name userName, user_password userPassword, user_email userEmail, user_info userInfo, head_img headImg, create_time createTime from sys_user where 1 = 1 and id = #{id} and user_name = #{userName} limit 0
where 、 set 、 trim 用法
where 用法
where 标签的作用:如果该标签包含的元素中有返回值,就插入一个 where ;如果 where后面的字符串是以 AND 和 OR 开头的,就将它们剔除。 select id, user_name userName, user_password userPassword, user_email userEmail, user_info userInfo, head_img headImg, create_time createTime from sys_user and user_name like concat('%', #{userName}, '%') and user_email = #{userEmail} 当 if 条件都不满足的时候, where 元素中没有内容,所以在 SQL 中不会出现 where
set 用法
set标签的作用:如果该标签包含的元素中有返回值,就插入一个set:如果set后面的字符串是以逗号结尾的,就将这个逗号剔除. update sys_user user_name = #{userName}, user_password = #{userPassword}, user_email = #{userEmail}, user_info = #{userInfo}, head_img = #{headImg, jdbcType=BLOB}, create_time = #{createTime, jdbcType=TIMESTAMP}, id = #{id}, where id = #{id}
trim 用法
where和set标签的功能都可以用trim标签来实现,并且在底层就是通过TrimSqlNode实现的。 where 标签对应 trim 的实现如下。 ... 这里的 AND 和 OR 后面的空格不能省略,为了避免匹配到 andes 、 orders 等单词 。实际的 prefixeOverrides 包含“AND”、“OR”、“AND\n ”、“OR\n ”、“AND\r”、"OR\r”、“AND\t ”、 “ OR \t ”, 不仅仅是上面提到的两个带空格的前缀 set 标签对应 的 trim 实现如下 。 trim 标签有如下属性。 prefix :当 trim 元素内包含内容时,会给内容增加 prefix 指定的前缀。 prefixOverrides :当 trim 元素内包含内容时,会把内容中匹配的前缀字符串去掉。 suffix :当 trim 元素内包含内容时,会给内容增加 suffix 指定的后缀。 suffixOverrides :当 trim 元素内包含内容时,会把内容中匹配的后缀字符串去掉。
foreach 用法
foreach可以对数组、Map或实现了工terable接口(如List、Set)的对象进行遍历。
foreach 实现 in 集合
select id, user_name userName, user_password userPassword, user_email userEmail, user_info userInfo, head_img headImg, create_time createTime from sys_user where id in #{id} foreach 包含以下属性: collection : 必填,值为要选代循环的属性名。这个属性值的情况有很多。 item:变量名,值为从迭代对象中取出的每一个值。 index :索引的属性名,在集合数组情况下值为当前索引值 , 当选代循环的对象是 Map类型时,这个值为 Map 的 key (键值)。 open:整个循环内容开头的字符串 。 close : 整个循环内容结尾的字符串。 separator :每次循环的分隔符 。
只有一个数组参数或集合参数
当参数类型为集合的时候,默认会转换为 Map 类型,井添加一个 key 为 collection 的值,如果参数类型是 List 集合,那么就继续添加一个 key 为 list的值,这样,当 collection=" list ”时, 就能得到这个集合,并对它进行循环操作。
有多个参数
当有多个参数的时候,要使用@ Param 注解给每个参数指定一个名字
参数是 Map 类型
将collection指定为对应Map中的key即可。 如果要循环所传入的Map,推荐使用@Param注解指定名字,此时可将collection设置为指定的名字,如果不想指定名字,就使用默认值_parameter
参数是一个对象
foreach 实现批量插入
insert into sys_user( user_name, user_password,user_email, user_info, head_img, create_time) values ( #{user.userName}, #{user.userPassword},#{user.userEmail}, #{user.userInfo}, #{user.headImg, jdbcType=BLOB}, #{user.createTime, jdbcType=TIMESTAMP})
foreach 实现动态 UPDATE
当参数是 Map 类型的时候, foreach 标签的工 ndex 属性值对应的不是索引值,而是 Map中的 key,利用这个 key 可以实现动态 UPDATE 。 update sys_user set ${key} = #{val} where id = #{id} 没有通过@ Param 注解指定参数名,因而 MyBati s 在内部的上下文中使用了默认值 _parameter 作为该参数的 key,所以在 XML 中 也使用了_parameter。
bind 用法
bind标签可以使用OGNL表达式创建一个变量井将其绑定到上下文中。 使用bind标签来避免由于更换数据库带来的一些麻烦。 select id, user_name userName, user_password userPassword, user_email userEmail, user_info userInfo, head_img headImg, create_time createTime from sys_user and user_name like concat('%', #{userName}, '%') and user_email = #{userEmail} bind 标签的两个属性都是必选项, name 为绑定到上下文的变量名, value 为 OGNL 表达式。
多数据库支持
在mybatis-config.xml文件中加入databaseidProvider配置
OGNL 用法
MyBatis 常用的 OGNL 表达式如下 。 1. e1 or e2 2. e1 and e2 3. e1 == e2 或 e1 eq e2 4 . e1 ! = e2 或 e1 neq e2 5. e1 lt e2 :小于 6. e1 lte e2 :小于等于,其他表示为 gt (大于)、 gte (大于等于) 7. e1 + e2 、 e1* e2 、 e 1/e2 、 e 1 - e2 、 e1 % e2 8. ! e 或 not e :非,取反 9. e.method(args ) : 调用对象方法 10. e.property : 对象属性值 11. e1[ e2 ] : 按索引取值( List 、数组和 Map) 12. @class@method(args ):调用类的静态方法 13. @class@field:调用类的静态字段值 and user_name like concat('%', #{userName}, '%')
5.Mybatis 代码生成器
XML 配置详解
generatorConfiguration标签下的3个子级标签,分别是properties、classPathEntry和context; resource : 指定 classpath 下的属性文件,类似 com/mypro 〕 ect/generatorConfig .properties 这样的属性值 • url : 指定文件系统上的特定位置,例如fi le : ///C : /myfolder/generatorConfig .properties 。 properties标签包含resource和url两个属性,只能使用其中一个属性来指定,同时出现则会报错。 classPathEntry标签最常见的用法是通过属性location指定驱动的路径; context标签用于指定生成一组对象的环境。例如指定要连接的数据库,要生成对象的类型和要处理的数据库中的表。运行MBG的时候还可以指定要运行的context。 property(0个或多个) plugin(0个或多个) commentGenerator(0个或1个〉 jdbcConnection(I个) javaTypeResolver(0个或l个〉 javaModelGenerator(1个) sqlMapGenerator(0个或1个) javaClientGenerator(0个或1个) table(I个或多个)
示例
运行MG
使用 Java 编写代码运行
只要在当前项目中 , 或者在当前项目的 classpath 中, 就可以直接使用;出现的问题最少,配置最容易;
从命令提示符运行
使用 Maven Plugin 运行
使用 Eclipse 插件运行
Example 介绍
使用 Example 查询能解决大部分复杂的单表操作,从一定程度上能减少工作量
6.Mybatis高级查询
高级结果映射
一对一映射
使用自动映射处理一对一关系
使用 resultMap 配置一对一映射
使用 resultMap 的 association 标签配置一对一映射
association 标签包含以下属性。 property :对应实体类中的属性名,必填项。 javaType : 属性对应的 Java 类型 。 resultMap : 可以直接使用现有的 resultMap ,而不需要在这里配置。 columnPrefix :查询列的前缀,配置前缀后,在子标签配置 result 的 .column 时可以省略前缀。
association 标签的嵌套查询
association 标签的嵌套查询常用的属性如下 。 select :另 一个映射查询的 id, MyBatis 会额外执行这个查询获取嵌套对象的结果 。 column :列名(或别名),将主查询中列的结果作为嵌套查询的 参数,配置方式如column={propl=coll , prop2=col2}, propl 和 prop2 将作为嵌套查询的参数。 fetch Type :数据加载方式,可选值为 lazy 和 eager,分别为延迟加载和积极加载 ,这个配置会覆盖全局的 lazyLoadingEnabled 配置 。
fetchType延迟加载
一对多映射
association 集合的嵌套结果映射
MyB ati s 在处理结果的时候 , 会判断结果是否相同 ,如果是相 同的结果 ,则 只会保留第一个结果, MyBatis 判断结果是否 相同时,最简单的情况就是在映射配置中至少有一个 id 标签 , 在 userMap 中配置如下。
collection 集合的嵌套查询
鉴别器映射
有时一个单独的数据库查询会返回很多不同数据类型(希望有些关联〉的结果集。discriminator鉴别器标签就是用来处理这种情况的 discriminator标签常用的两个属性如下。 column:该属性用于设置要进行鉴别比较值的列。 javaType:该属性用于指定列的类型,保证使用相同的Java类型来比较值。 discriminator标签可以有l个或多个case标签,case标签包含以下三个属性。 value:该值为discriminator指定column用来匹配的值。 resultMap:当column的值和value的值匹配时,可以配置使用resultMap指定的映射,resultMap优先级高于resultType。 resultType:当column的值和value的值匹配时,用于配置使用resultType指定的映射。
存储过程
指定参数的mode(模式),可选值为IN、OUT、工NOUT三种。入参使用IN,出参使用OUT,输入输出参数使用INOUT。 IN和OUT两种模式的区别是,OUT模式的参数必须指定jdbcType。这是因为在IN模式下,MyBatis提供了默认的jdbcType,在OUT模式下没有提供。 另外在使用Oracle数据库时,如果入参存在null的情况,那么入参也必须指定jdbcType。 {call select_user_by_id( #{id, mode=IN}, #{userName, mode=OUT, jdbcType=VARCHAR}, #{userPassword, mode=OUT, jdbcType=VARCHAR}, #{userEmail, mode=OUT, jdbcType=VARCHAR}, #{userInfo, mode=OUT, jdbcType=VARCHAR}, #{headImg, mode=OUT, jdbcType=BLOB, javaType=_byte[]}, #{createTime, mode=OUT, jdbcType=TIMESTAMP} )}
mysql
oracle使用游标
使用游标类型时,需要注意将jdbcType设置为CURSOR,将javaType设置为ResultSet
使用枚举或其他对象
使用 MyBatis 提供的枚举处理器
提供了一个 org . apache .ibatis . type .EnumOrdinalTypeHandler 处理器,这个处理器使用枚举的索引进行处理 javaType=” tk.mybatis.simple.type.Enabled" handler=” org . apache.ibatis.type.EnumOrdinalTypeHandler”/>
使用自定义的类型处理器
对Java8日期(JSR-310)支持
org.mybatis mybatis-typehandlers - jsr310 l.0 . 2
7.MyBaits缓存配置
一般提到 MyBatis 缓存的时候,都是指二级缓存。 一级缓存( 也叫本地缓存〉默认会启用,并且不能控制。
一级缓存
一级缓存是和 SqlSession 绑定的,只存在于 SqlSession的生命周期中。
二级缓存
配置
Mapper.xml 中配置二级缓存
映射语句文件中的所有SELECT语句将会被缓存。 •映射语句文件中的所有时SERT、UPDATE、DELETE语句会刷新缓存。 缓存会使用LeastRecentlyUsed(LRU,最近最少使用的)算法来收回。 •根据时间表(如noFlushInterval,没有刷新间隔),缓存不会以任何时间顺序来刷新。 缓存会存储集合或对象(无论查询方法返回什么类型的值)的1024个引用。 •缓存会被视为read/write(可读/可写)的,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。 eviction(收回策略) >LRU(最近最少使用的):移除最长时间不被使用的对象,这是默认值。 >FIFO(先进先出〉:按对象进入缓存的顺序来移除它们。 };;>SOFT(软引用):移除基于垃圾回收器状态和软引用规则的对象。 };;>WEAK(弱引用):更积极地移除基于垃圾收集器状态和弱引用规则的对象。 flushinterval(刷新间隔〉。可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况不设置,即没有刷新间隔,缓存仅仅在调用语句时刷新。 size(引用数目)。可以被设置为任意正整数,要记住缓存的对象数目和运行环境的可用内存资源数目。默认值是1024。 readOnly(只读)。属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改,这提供了很重要的性能优势。可 读写的缓存会通过序列化返回缓存对象的拷贝,这种方式会慢一些,但是安全,因此默认是false。
Mapper 接口中配置二级缓存
@CacheNamespace
@CacheNarnespaceRef(RoleMapper . class)
使用
使用 SerializedCache 序列化缓存
集成 EhCache 缓存
特点
EhCache 是一个纯牌的 Java 进程内的缓存框架,具有快速、精干等特点。 EhCache主要的特性如下 。 • 快速 。 简单 。 • 多种缓存策略 。 • 缓存数据有内存和磁盘两级,无须担心容量问题 。 缓存数据会在虚拟机重启 的过程中写入磁盘。 可 以通过 RMI、可插入 API 等方式进行分布式缓存。 . 具有缓存和缓存管理器的侦听接口。 • 支持多缓存管理器实例 以及一个实例的多个缓存区域 。
配置
copyOnRead
判断从缓存中读取数据时是返回对象的引用还是复制一个对象返回。 默认情况下是false,即返回数据的引用,这种情况下返回的都是相同的对象,和MyBatis默认缓存中的只读对象是相同的。如果设置为true,那就是可读写缓存,每次读取缓存时都会复制一个新的实例。
copyOnWrite
判断写入缓存时是直接缓存对象的引用还是复制一个对象然后缓存,默认也是false。如果想使用可读写缓存,就需要将这两个属性配置为true,如果使用只读缓存,可以不配置这两个属性,使用默认值false即可。
集成 Redis 缓存
Redis是一个高性能的key-value数据库。
脏数据的产生和避免
参照缓存
二级缓存适用场景
以查询为主的应用中,只有尽可能少的增、删、改操作。 绝大多数以单表操作存在时,由于很少存在互相关联的情况,因此不会出现脏数据。 可以按业务划分对表进行分组时,如关联的表比较少,可以通过参照缓存进行配置。
8.MyBatis插件开发
拦截器接口
Interceptor(org.apache.ibatis.plugin.Interceptor),在实现类中对拦截对象和方法进行处理。 •Executor(update、query、flushStatements、commit、rollback、 getTransaction、close、isClosed) •ParameterHandler(getParameterObject、setParameters) •ResultSetHandler(handleResultSets、handleCursorResultSets、 handleOutputParameters) •StatementHandler(prepare、parameterize、batch、update、query)
拦截器签名
@Intercepts 注解中的属性是一个@ Signature (签名)数组,可以在同 一个拦截器中同时拦截不同的接口和方法。 @Intercepts({ @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) }) public class ResultSetInterceptor implements Interceptor { @Signature 注解包含以下三个属性。 type : 设置拦截 的接口,可选值是前面提到的 4 个接口 。 method : 设置拦截接口中的方法名 , 可选值是前面 4 个接口对应的方法,需要和接口匹配 。 args : 设置拦截方法的参数类型数组 , 通过方法名和参数类型可以确定唯一一个方法 。
Executor 接口
ParameterHandler 接口
ResultSetHandler 接口
StatementHandler 接口
下画线键值转小写驼峰形式插件
分页插件
PageInterceptor 拦截器类
Dialect 接口
MySqlDialect 实现
9.Spring集成MyBaits
创建基本的 Maven Web 顶目
集成 Spring 和 Spring MVC
集成 MyBatis
10.Spring Boot 集成 MyBatis
基本的 Spring Boot 顶目
集成 MyBatis
MyBatis Starter 配置
11.MyBatis 开源项目
Git入门
Git 是一个分布 式 的版本控制系统。 git config --global user.name 你的名字 git config --global user.email 你的邮箱 查看当前的配置 git config - - list
初始化和克隆仓库
在项目的顶层目录或者具体某个目录中添加一个名为 “.gitignore”的文件。
本地操作
远程操作
GitHub 入门
GitHub 是一个通过 Git 进行版本控制的软件源代码托管平台。
MyBatis 源码讲解
MyBatis 测试用例