本篇文章是「深入浅出MyBatis:技术原理与实践」书籍的总结笔记。

上一篇总结了MyBatis的配置,详细说明了各个配置项,其中提到了映射器,它是MyBatis最强大的工具,也是使用最多的工具。

通过映射器,可以很容易的进行数据的增删改查操作,我们抽象下进行这些操作的关键点:传递查询参数、组装各种场景下的查询条件、关联查询、将查询结果映射为Java Bean对象或集合等。另外,可以通过延迟加载、缓存提高数据查询的性能。

文章索引:

  1. JDBC和MyBatis介绍
  2. MyBatis的所有配置
  3. 「映射器」全了解
  4. 反射和动态代理基础

本篇就按照这个思路进行总结,首先列举下映射器的主要元素,每个元素提供的配置项和作用,然后重点介绍参数、结果映射、延迟加载、缓存、动态SQL等功能。

映射器的主要元素

映射器是由Java接口和XML文件(或注解)共同组成的,Java接口主要定义调用者接口,XML文件是配置映射器的核心文件,包括以下元素:

  • select 查询语句,可以自定义参数,返回结果集;
  • insert 插入语句,返回一个整数,表示插入的条数;
  • update 更新语句,返回一个整数,表示更新的条数;
  • delete 删除语句,返回一个整数,表示删除的条数;
  • sql 允许定义一部分SQL,然后再各个地方引用;
  • resultMap 用来描述从数据库结果集中来加载对象,还可以配置关联关系;
  • cache 给定命名空间的缓存配置;

增、删、改、查操作

查找

执行select语句前,需要定义参数,执行后,也提供了强大的映射规则或自动映射,将返回的结果集绑定到java bean中。

select元素有很多配置项,下面简单说明下:

  • paramterType:传入的参数类型,可以是基本类型、map、自定义的java bean;
  • resultType:返回的结果类型,可以是基本类型、自定义的java bean;
  • resultMap:它是最复杂的元素,可以配置映射规则、级联、typeHandler等,与ResultType不能同时存在;
  • flushCache:在调用SQL后,是否要求清空之前查询的本地缓存和二级缓存,主要用于更新缓存,默认为false;
  • useCache:启动二级缓存的开关,默认只会启动一级缓存;
  • timeout:设置超时参数,等超时的时候将抛出异常,单位为秒;
  • fetchSize:获取记录的总条数设定;

比如根据米聊号获取用户信息:

<select id="findByMiliao" parameterType="string" resultType="User">selectu.*from mxt_user uwhere u.miliao=#{miliao}
</select>
复制代码

上一篇介绍配置时,有个设置项autoMappingBehavior,默认为自动映射没有定义嵌套结果集映射的结果集;还有设置项mapUnderscoreToCamelCase,设置为true时,会自动将以「下划线」命名的数据库字段名,自动映射为以「驼峰式」命名的POJO。

传递多个参数时,有3种方式:

  • 使用Map参数;
  • 使用注解方式传递;
  • 使用java bean;

使用注解方式如下:

public List<Role> findRoleByNameAndNote(@Param("roleName") String rolename,
@Param("note") String note);
复制代码

使用Map传递参数,会导致业务可读性丧失,导致以后扩展和维护不方便,不建议;如果参数个数<=5,建议使用注解的方式,因为过多参数将给调用者带来困难;如果参数个数>5,建议使用JavaBean方式;

使用resultMap映射结果集,后面会单独介绍。

insert

属性和select大部分都相同, 说下3个不同的属性:

  • keyProperty:指定哪个列是主键,如果是联合主键可以用逗号隔开;
  • keyColumn:指定第几列是主键,不能和keyProperty共用;
  • useGeneratedKeys:是否使用自动增长,默认为false;

当useGeneratedKeys设为true时,在插入的时候,会回填Java Bean的id值,通过返回的对象可获取主键值。

如果想根据一些特殊关系设置主键的值,可以在insert标签内使用selectKey标签,比如:如果t_role没有记录,则需要设置为1,否则取最大id加2:

<insert id="insertRole" useGeneratedKeys="true" keyProperty="id" ><selectKey keyProperty="id" resultType="int" order="before">select if(max(id) is null,1,max(id)+2) as newId from t_role</selectKey>
</insert>
复制代码
update和delete

比较简单,就不过多介绍了。

参数

上面已经介绍了参数传递,另外可以指定参数的类型去让对应的typeHandler处理它们。

#{age , javaType=int , jdbcType=NUMERIC }
复制代码

还可以对一些数值型的参数设置其保存的精度

#{price, javaType=double , jdbcType=NUMERIC , numericScale=2 }
复制代码

一般都是传递字符串,设置的参数#{name}大部分情况下,会创建预编译语句,但有时候传递的是SQL语句本身,不是需要的参数,可以通过$符号表示,比如传递参数columns为"col1,col2,col3",可以写成下面语句:

select ${columns} from t_tablename
复制代码

但要注意sql的安全性,防止sql注入。

sql元素

定义:

<sql id="role_columns">id,role_name,note
</sql>
复制代码

使用:

<include refid="role_columns"><property name="prefix" value="r" />
</include>
复制代码

结果映射

元素介绍

resultMap是MyBatis里面最复杂的元素,它的作用是定义映射规则、级联的更新、定制类型转换器等。

由以下元素构成:

<resultMap><constructor> <!-- 配置构造方法 --><idArg/><arg/></constructor><id/> <!--指明哪一列是主键--><result/> <!--配置映射规则--><association/> <!--一对一--><collection/> <!--一对多--><discriminator> <!--鉴别器级联--><case/></discriminator>
</resultMap>
复制代码

有的实体不存在没有参数的构造方法,需要使用constructor配置有参数的构造方法:

<resultMap id="role" type="com.xiaomi.kfs.mcc.core.domain.Role"><constructor><idArg column="id" javaType="int"/><arg column="role_name" javaType="string"/></constructor>
</resultMap>
复制代码

id指明主键列,result配置数据库字段和POJO属性的映射规则:

<resultMap id="role" type="com.xiaomi.kfs.mcc.core.domain.Role"><id property="id" column="id" /><result property="roleName" column="role_name" /><result property="note" column="note" />
</resultMap>
复制代码

association、collection用于配置级联关系的,分别为一对一和一对多,实际中,多对多关系的应用不多,因为比较复杂,会用一对多的关系把它分解为双向关系。

discriminator用于这样一种场景:比如我们去体检,男和女的体检项目不同,如果让男生去检查妇科项目,是不合理的, 通过discriminator可以根据性别,返回不同的对象。

级联关系的配置比较多,就不在此演示了,可查看文档进行了解。

延迟加载

级联的优势是能够方便地获取数据,但有时不需要获取所有数据,这样会多执行几条SQL,性能下降,为了解决这个问题,需要使用延迟加载,只要使用相关级联数据时,才会发送SQL去取回数据。

在MyBatis的配置中有2个全局的参数 lazyLoadingEnabled 和 aggressiveLazyLoading ,第一个的含义是是否开启延迟加载功能,第二个的含义是对任意延迟加载属性的调用,会使延迟加载的对象完整加载,否则只会按需加载。

再理解下aggressiveLazyLoading属性,比如学生对象的关联对象如下:

当访问学生信息的时候,会根据鉴别器把健康的情况也会查找出来;当访问课程成绩的时候,同时也会把学生证信息查找出来,因为在默认情况下,MyBatis是按层级延迟加载的。 但这不是我们需要的,并不希望在访问成绩的时候,去加载学生证的信息,可以设置aggressiveLazyLoading为false,按需进行延迟加载数据。

上面的2个属性都是全局设置,也可以在association和collection元素上加上属性值fetchType,它有两个取值eager和lazy。

缓存

在没有显示配置缓存时,只开启一级缓存,一级缓存是相对于同一个SqlSession而言的,在参数和SQL完全一样的情况下,使用同一个SqlSession对象调用同一个Mapper的方法,只会执行一次SQL。

如果是不同的SqlSession对象,因为不同SqlSession是相互隔离的,即使用相同的Mapper、参数和方法,还是会再次发送SQL到数据库去执行。

二级缓存是SqlSessionFactory层面上的,需要进行显示配置,实现二级缓存的时候,要求POJO必须是可序列化的,只需要简单配置即可:

<cache />
复制代码

这样很多设置是默认的,有如下属性可以配置:

  • eviction:代表缓存回收策略,可选值有LRU最少使用、FIFO先进先出、SOFT软引用,WEAK弱引用;
  • flushInterval:刷新间隔时间,单位为毫秒,如果不配置,当SQL被执行时才会刷新缓存;
  • size:引用数目,代表缓存最多可以存储多少对象,不宜设置过大,设置过大会导致内存溢出;
  • readOnly:只读,意味着缓存数据只能读取不能修改;

在大型服务器上,可能会使用专用的缓存服务器,比如Redis缓存,可以通过实现org.apache.ibatis.cache.Cache接口很方便的实现:

public interface Cache {String getId(); //缓存编号void putObject(Object var1, Object var2); //保存对象Object getObject(Object var1); //获取对象Object removeObject(Object var1); //移除对象void clear(); //清空缓存int getSize(); //获取缓存对象大小ReadWriteLock getReadWriteLock(); //获取缓存的读写锁
}
复制代码

动态SQL

很多时候,需要根据不同的场景组装查询条件,MyBatis提供对SQL语句动态的组装能力。

主要提供以下几种元素:

  • if:判断语句,但条件分支判断;
  • choose (when、otherwise):多条件分支判断;
  • trim (where、set):处理一些SQL拼装问题;
  • foreach:循环语句,在in语句等列举条件常用;
  • bind:通过OGNL表达式去自定义一个上下文变量,可以方便使用;

trim可以处理 and 和 逗号 拼接的问题,举例如下:

<select id="findRoles" parameterType="string" >select id,role_name,note from t_role<trim prefix="where" prefixOverrides="and"><if test="roleName!=null and roleName!=''">and role_name like concat('%',#{roleName},'%')</if></trim>
</select>
复制代码

另外,可以使用set元素设置更新的字段列表:

<update id="updateRole" parameterType="role">update t_role<set><if test="roleName!=null and roleName!=''">role_name=#{roleName},</if><if test="note!=null and note!=''">note=#{note}</if></set>where id=#{id}
</update>
复制代码

下一篇会介绍MyBatis的解析和运行原理。

欢迎扫描下方二维码,关注我的个人微信公众号 ~

深入浅出MyBatis:「映射器」全了解相关推荐

  1. 【MyBatis】 ---- 映射器(接口+XML文件)

    目录 一. 配置元素 1. select元素 2. insert元素 3. sql元素 4. resultMap元素 5. resultMap元素中的级联 (代码github) 一.映射器的配置元素 ...

  2. (八)mybatis之映射器

    映射器 映射器是由Java接口和XML文件(或注解)共同组成的,作用如下: ①   定义参数类型. ②   描述缓存. ③   描述SQL语句. ④   定义查询结果和POJO的映射关系. 以下用两种 ...

  3. Akka 指南 之「调度器」

    温馨提示:Akka 中文指南的 GitHub 地址为「akka-guide」,欢迎大家Star.Fork,纠错. 文章目录 调度器 依赖 简介 默认调度器 查找调度器 为 Actor 设置调度器 调度 ...

  4. 【Java综合专栏】「引领序幕」全链路追踪原理之Java Agent探针的技术介绍(上篇)

    前提概要 Java调式.热部署.JVM背后的支持者Java Agent: 各个 Java IDE 的调试功能,例如 eclipse.IntelliJ : 热部署功能,例如 JRebel.XRebel. ...

  5. mybatis传递多个参数_深入浅出MyBatis:MyBatis解析和运行原理

    原文:https://juejin.im/post/5abcbd946fb9a028d1412efc 本篇文章是「深入浅出MyBatis:技术原理与实践」书籍的总结笔记. 上一篇介绍了反射和动态代理基 ...

  6. 5、mybatis中的映射器

    目录 1.映射器是什么? 2.自定义sql和使用的分类 2.1 根据定义sql的两种方式分类 2.2 根据使用方式分类 mybatis在实际使用时,最主要的还是映射器.这一篇大体介绍一下映射器,但是有 ...

  7. 怎么通过id渲染页面_「快页面」动态配置化页面渲染器原理介绍

    引言 「快页面」是知乎内部一个快速搭建后台管理页面的平台,使用者仅用半小时即可将一个常规复杂度的后台页面开发完成. 「快页面」平台的基石是它的「渲染器」,一个能将 JSON 配置渲染成页面的 Reac ...

  8. 深入浅出MyBatis:JDBC和MyBatis介绍

    为什么80%的码农都做不了架构师?>>>    最近在休陪产假,时间比较零碎,准备看2本书充实下,一本是「深入浅出MyBatis:技术原理与实践」,一本是「RabbitMQ实战:高效 ...

  9. 哔哩哔哩「会员购」业务网关的研发赋能实践

    作者 沈佳伟 哔哩哔哩会员购架构师 写在前面 网关是个每隔一段时间就会被请出来「鞭尸」的概念,概念本身的起源已经无从考究.随着微服务和云原生的兴起,网关也伴随着不同的使用场景在各个领域进行细分和进化. ...

最新文章

  1. 服务器群安装系统,服务器安装总结
  2. 更新view是可以update到表的
  3. Robotium中定位Android客户端疑难元素
  4. 目标检测特殊层:PSROIPooling详解
  5. python单选按钮重置_python – Tkinter单选按钮初始化错误
  6. android——获取ImageView上面显示的图片bitmap对象
  7. linux部署jenkins,tomcat9
  8. 25马5跑道,求最快的五匹马的需要比赛的次数
  9. C++11多线程实现银行存取款案例
  10. eclipse集成python插件
  11. 优化mysql的21个建议_MySQL优化小建议
  12. 【jQuery学习】—实现弹幕效果
  13. read time out解决方法_quot;read-on-writequot; in InnoDB
  14. python selenium 元素定位总结(转载)
  15. 资源调度_提前计划+实时调度,实现月台资源高效利用
  16. android使用的数据,在 Android 应用中使用数据 - Xamarin | Microsoft Docs
  17. python写代码酷炫插件_使用 Python 制作酷炫多彩的 Jenkins 插件词云图
  18. 日语学习之——学习技巧
  19. linux gt240驱动下载,NVIDIA官方发布Linux 256.53正式版驱动
  20. 上海泗博自动化 Modbus 转以太网模块应用于某污水处理系统

热门文章

  1. 博客杂志CMS模板,wpdx3.6破解版源码WordPress主题
  2. java继承静态方法,是否在Java中继承了静态方法?
  3. sublime 插件安装;sublime的 babel、sublime-jsfmt插件
  4. java 方法 链路 trace_arthas命令trace追踪方法链路
  5. 基于JFinal框架开发的企业办公系统-JFinalOA v1.1源码
  6. DataGrid 导出到 Excel 的帮助类
  7. MediaWiki/安装
  8. 面向普通人的 PHP 加密
  9. magento 上传图片slider Multiple Banner Extension
  10. iPhone入门教程 (视频)