1.1为什么需要ORM框架?

传统的JDBC编程存在的弊端:

ü 工作量大,操作数据库至少要5步;

ü 业务代码和技术代码耦合;

ü 连接资源手动关闭,带来了隐患;

MyBatis前身是iBatis,其源于“Internet”和“ibatis”的组合,本质是一种半自动的ORM框架,除了POJO和映射关系之外,还需要编写SQL语句;Mybatis映射文件三要素:SQL、映射规则和POJO;

1.2 MyBatis快速入门

步骤如下:

  1. 加入mybatis的依赖,版本3.5.x
  2. 添加mybatis的配置文件,包括MyBatis核心文件和mapper.xml文件
  3. 场景介绍:基于t_user表单数据查询、多数据查询;
  4. 编写实体类、mapper接口以及mapper xml文件;
  5. 编写实例代码:com.enjoylearning.mybatis.MybatisDemo. quickStart

核心类分析:

  1. SqlSessionFactoryBuilder:读取配置信息创建SqlSessionFactory,建造者模式,方法级别生命周期;
  2. SqlSessionFactory:创建Sqlsession,工厂单例模式,存在于程序的整个生命周期;
  3. SqlSession:代表一次数据库连接,一般通过调用Mapper访问数据库,也可以直接发送SQL执行, ;线程不安全,要保证线程独享(方法级);
  4. SQL Mapper:由一个Java接口和XML文件组成,包含了要执行的SQL语句和结果集映射规则。方法级别生命周期;

1. resultType还是resultMap?

2.1 resultType

resultType:当使用resultType做SQL语句返回结果类型处理时,对于SQL语句查询出的字段在相应的pojo中必须有和它相同的字段对应,而resultType中的内容就是pojo在本项目中的位置。

自动映射注意事项 :

  1. 前提:SQL列名和JavaBean的属性是一致的;
  2. 使用resultType,如用简写需要配置typeAliases (别名);
  3. 如果列名和JavaBean不一致,但列名符合单词下划线分割,Java是驼峰命名法,则mapUnderscoreToCamelCase可设置为true;

2.2 resultMap

resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,在对复杂语句进行联合映射的时候,它很可能可以代替数千行的同等功能的代码。 ResultMap 的设计思想是,简单的语句不需要明确的结果映射,而复杂一点的语句只需要描述它们的关系就行了。

属性

描述

id

当前命名空间中的一个唯一标识,用于标识一个result map.

type

类的完全限定名, 或者一个类型别名.

autoMapping

如果设置这个属性,MyBatis将会为这个ResultMap开启或者关闭自动映射。这个属性会覆盖全局的属性 autoMappingBehavior。默认值为:unset。

使用场景总结:1. 字段有自定义的转化规则;2. 复杂的多表查询

2.3到底应该用resultType还是resultMap?

强制使用resultMap, 不要用 resultClass 当返回参数,即使所有类属性名与数据库字段一一对应,也需要定义;见《Java开发手册1.5》之5.4.3;

3. 怎么传递多个参数?

传递参数有三种方式:

方式

描述

使用map传递参数

可读性差,导致可维护性和可扩展性差,杜绝使用

使用注解传递参数

直观明了,当参数较少一般小于5个的时候,建议使用

使用Java Bean的方式传递参数

当参数大于5个的时候,建议使用

建议不要用Map作为mapper的输入和输出,不利于代码的可读性和可维护性;见《Java开发手册1.5》之5.4.6;

4. 怎么样获取主键?

4.1 通过insert/update标签相关属性

属性

描述

useGeneratedKeys

(仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。

keyProperty

(仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

注意:自增长序号不是简单的行数+1,而是序号最大值+1;

4.2 通过selectKey元素

属性

描述

keyProperty

selectKey 语句结果应该被设置的目标属性。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

resultType

结果的类型。MyBatis 通常可以推算出来,但是为了更加确定写上也不会有什么问题。MyBatis 允许任何简单类型用作主键的类型,包括字符串。如果希望作用于多个生成的列,则可以使用一个包含期望属性的 Object 或一个 Map。

order

这可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty 然后执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后获取主键字段;mysql数据库自增长的方式order设置为After,oracle数据库通过sequnce获取主键order设置为Before

Oracle通过sequnce获取主键示例:

<selectKey  keyProperty=“id” order= " Before" resultType="int">

select SEQ_ID.nextval from dual

</selectKey>

Mysql通过自增长序号获取主键示例:

<selectKey keyProperty="id" order="AFTER" resultType="int">

select LAST_INSERT_ID()

</selectKey>

5. SQL元素和SQL的参数

SQL元素:用来定义可重用的 SQL 代码段,可以包含在其他语句中;

SQL参数:向sql语句中传递的可变参数,分为预编译#{}和传值${}两种

ü 预编译 #{}:将传入的数据都当成一个字符串,会对自动传入的数据加一个单引号,能够很大程度防止sql注入;

ü 传值${}:传入的数据直接显示生成在sql中,无法防止sql注入;适用场景:动态报表,表名、选取的列是动态的,order by和in操作, 可以考虑使用$

示例代码:com.enjoylearning.mybatis.MybatisDemo.testSymbol

建议:sql.xml 配置参数使用:#{},#param# 不要使用${} 此种方式容易出现 SQL 注入。见《Java开发手册1.5》之5.4.4;

6. 动态SQL

6.1 动态SQL元素

元素

作用

备注

if

判断语句

单条件分支判断

choose、when、otherwise

相当于java的case when

多条件分支判断

Trim、where、set

辅助元素

用于处理sql拼装问题

foreach

循环语句

在in语句等列举条件常用,常用于实现批量操作

6.2 示例代码说明

 

 

6.3 通过Mybatis怎么样进行批量的操作

    1. 通过foreach动态拼装SQL语句
    2. 使用BATCH类型的excutor

7. 代码生成器

MyBatis Generator:MyBatis 的开发团队提供了一个很强大的代码生成器,代码包含了数据库表对应的实体类 、Mapper 接口类、 Mapper XML 文件等,这些代码文件中几乎包含了全部的单表操作方法,使用 MBG 可以极大程度上方便我们使用 MyBatis,还可以减少很多重复操作;MyBatis Generator的核心就是配置文件,完整的配置文件见:

运行MGB的方式有三种,见下表:

方式

运行代码

推荐使用场景

作为 Maven Plugin运行

mvn mybatis-generator:generate

对逆向工程定制较多,项目工程结构比较单一的情况

运行Java 程序使用 XML配置文件

com.enjoylearning.mybatis.MybatisDemo.mybatisGeneratorTest

从命令提示符 使用 XML 配置文件

java -jar mybatis-generator-core-x.x.x.jar -configfile generatorConfig.xml

具体见网盘:逆向工程

对逆向工程定制较少,项目工程结构比较复杂的情况

8. 关联查询

8.1 关联查询几个需要注意的细节

  1. 超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引;见《Java开发手册1.5》之5.2.2;
  2. 不得使用外键与级联,一切外键概念必须在应用层解决;见《Java开发手册1.5》之5.3.6;
  3. 字段允许适当冗余,以提高查询性能,但必须考虑数据一致;见《Java开发手册1.5》之5.1.13;

关联元素:association用于表示一对一关系,collection用于表示一对多关系;

关联方式:

ü 嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集

ü 嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型

8.2 一对一关联嵌套结果方式

association标签 嵌套结果方式 常用属性:

ü property :对应实体类中的属性名,必填项。

ü javaType :属性对应的 Java 类型 。

ü resultMap :可以直接使用现有的 resultMap ,而不需要在这里配置映射关系。

ü columnPrefix :查询列的前缀,配置前缀后,在子标签配置 result 的 column 时可以省略前缀

示例代码:com.enjoylearning.mybatis.testOneToOne.

开发小技巧:

  1. resultMap可以通过使用extends实现继承关系,简化很多配置工作量;
  2. 关联的表查询的类添加前缀是编程的好习惯;
  3. 通过添加完整的命名空间,可以引用其他xml文件的resultMap;

8.3 一对一关联嵌套查询方式

association标签 嵌套查询方式 常用属性:

ü select :另 一个映射查询的 id, MyBatis 会额外执行这个查询获取嵌套对象的结果 。

ü column :列名(或别名),将主查询中列的结果作为嵌套查询的参数。

ü fetchType :数据加载方式,可选值为 lazy 和 eager,分别为延迟加载和积极加载 ,这个配置会覆盖全局的 lazyLoadingEnabled 配置;

示例代码:com.enjoylearning.mybatis.testOneToOne().

嵌套查询会导致“N+1 查询问题”,导致该问题产生的原因:

  1. 你执行了一个单独的 SQL 语句来获取结果列表(就是“+1”)。
  2. 对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。

这个问题会导致成百上千的 SQL 语句被执行。这通常不是期望的。

解决“N+1 查询问题”的办法就是开启懒加载、按需加载数据,开启懒加载配置:

在<select>节点上配置“fetchType=lazy”

在MyBatis核心配置文件中加入如下配置:

<!-- 开启懒加载 ,当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。默认:true -->

<setting name="aggressiveLazyLoading" value="false" />

8.4 一对多关联

collection 支持的属性以及属性的作用和 association 完全相同。mybatis会根据id标签,进行字段的合并,合理配置好ID标签可以提高处理的效率;

开发小技巧:如果要配置一个相当复杂的映射,一定要从基础映射开始配置,每增加一些配置就进行对应的测试,在循序渐进的过程中更容易发现和解决问题 。

8.5 多对多关联

要实现多对多的关联,需要满足如下两个条件:

  1. 先决条件一:多对多需要一种中间表建立连接关系;
  2. 先决条件二:多对多关系是由两个一对多关系组成的,一对多可以也可以用两种方式实现;

9. 缓存

MyBatis 包含一个非常强大的查询缓存特性,使用缓存可以使应用更快地获取数据,避免频繁的数据库交互 ;

9.1一级缓存

一级缓存默认会启用,想要关闭一级缓存可以在select标签上配置flushCache=“true”;一级缓存存在于 SqlSession 的生命周期中,在同一个 SqlSession 中查询时, MyBatis 会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个 Map对象中。如果同一个 SqlSession 中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当 Map 缓存对象中己经存在该键值时,则会返回缓存中的对象;任何的 INSERT 、UPDATE 、 DELETE 操作都会清空一级缓存;

9.2二级缓存

二级缓存也叫应用缓存,存在于 SqlSessionFactory 的生命周期中,可以理解为跨sqlSession;缓存是以namespace为单位的,不同namespace下的操作互不影响。在MyBatis的核心配置文件中 cacheEnabled参数是二级缓存的全局开关,默认值是 true,如果把这个参数设置为 false,即使有后面的二级缓存配置,也不会生效;

要开启二级缓存,你需要在你的 SQL Mapper文件中添加配置:

<cache eviction=“LRU" flushInterval="60000" size="512" readOnly="true"/>

这段配置的效果如下:

ü 映射语句文件中的所有 select 语句将会被缓存。

ü 映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。

ü 缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。

ü 根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。

ü 缓存会存储列表集合或对象(无论查询方法返回什么)的 512个引用。

ü 缓存会被视为是 read/write(可读/可写)的缓存;

开发建议:使用二级缓存容易出现脏读,建议避免使用二级缓存,在业务层使用可控制的缓存代替更好;

9.3缓存调用过程

缓存的调用过程如下:

调用过程解读:

  1. 每次与数据库的连接都会优先从缓存中获取数据
  2. 先查二级缓存,再查一级缓存
  3. 二级缓存以namespace为单位的,是SqlSession共享的,容易出现脏读,建议避免使用二级缓存
  4. 一级缓存是SqlSession独享的,建议开启;

MyBatis开发重点知识的更多相关文章

  1. 【springmvc+mybatis项目实战】杰信商贸-6.重点知识回顾

    1.重点知识回顾 Maven1)覆盖仓库文件,实际企业开发,公司会架一个测试服务器,在测试服务器中架私服.我们开发人员的程序,都连接私服.当本地没有项目中要使用的jar,Myeclipse maven ...

  2. Android开发重点难点1:RelativeLayout(相对布局)详解

    前言 啦啦啦~博主又推出了一个新的系列啦~ 之前的Android开发系列主要以完成实验的过程为主,经常会综合许多知识来写,所以难免会有知识点的交杂,给人一种混乱的感觉. 所以博主推出“重点难点”系列, ...

  3. AJAX重点知识的心得体会

    下面就为大家带来一篇 AJAX重点知识的心得体会.学习还是有点帮助的,给大家做个参考吧. AJAX是什么? 是Asynchronous Javascript And XML的首字母的缩写, 它不是一门 ...

  4. mybatis开发,你用 xml 还是注解?我 pick ...

    最近在看公司项目时发现有的项目mybatis是基于注解开发的,而我个人的习惯是基于xml文件开发. 对于mybatis注解开发的原理理解不够,于是翻阅了部分源码,写下此文.主要介绍了mybatis开发 ...

  5. IOS开发基础知识碎片-导航

    1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...

  6. 移动端 Web 开发前端知识整理

    文章来源: http://www.restran.net/2015/05/14/mobile-web-front-end-collections/ 最近整理的移动端 Web 开发前端知识,不定期更新. ...

  7. MyBatis学习--mybatis开发dao的方法

    简介 使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法. 主要概念介绍: MyBatis中进行Dao开发时候有几个重要的类,它们是SqlSessionFac ...

  8. 四 mybatis开发dao的方法

    mybatis开发dao的方法 1.1     SqlSession使用范围 1.1.1     SqlSessionFactoryBuilder //以流的方式读取总的配置文件 Reader rea ...

  9. 【转载】STL"源码"剖析-重点知识总结

    原文:STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点 ...

随机推荐

  1. java简单内存图

    一 内存的分区 二 以数组为例画内存图 代码: class Demo01 { public static void main(String[] args) { //1.数据类型[] 数组名=new 数 ...

  2. 2020-06-16:Redis hgetall时间复杂度?

    福哥答案2020-06-16: 时间复杂度是O(N).时间复杂度:O(N) where N is the size of the hash.

  3. C#算法设计排序篇之02-快速排序(附带动画演示程序)

    快速排序(Quick Sort) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/677 访问. 快速排序由C. A. R ...

  4. Homekit_DoHome_智能通断器

    本款通断器适用于IOS和android系统用户,苹果用户可以非常方便的使用siri进行有效控制,android用户需要下载Dohome App进行操作,同时支持市面上主流的智能音箱进行控制. 对于an ...

  5. 使用MIPS完成汇编程序——选择排序实现

    题目: 从键盘输入10个无符号字数并从大到小进行排序,排序结果在屏幕上显示出来.要求能输入数字 和输出数字 且由大到小来排列 1.代码以及伪代码: 首先写出对应c++代码然后把c++代码翻译成汇编语言 ...

  6. 随机陷阱和P值

    如果让大家写一个50次的抛硬币实验的可能结果(头像H或字T),多半人在连续三个一样的后,会换一下.因为大家都知道,连续一样的越多,概率越小,越不可能发生.大部分人不会去想,其实HHHTT和HHHHH发 ...

  7. Vue管理系统前端系列四组件拆分封装

    目录 组件封装 首页布局拆分后结构 拆分后代码 状态管理中添加 app 模块 组件封装 在上一篇记录中,首页中有太多的代码,为了避免代码的臃肿,需要对主要的功能模块拆分,来让代码看起来更简洁,且能进行 ...

  8. 第3篇 Scrum 冲刺博客(专✌️团队)

    目录 一.站立式会议 1.1 会议照片 1.2 成员完成情况 二.项目燃尽图 三.成员代码/文档签入记录 3.1 代码签入 3.2 Issue链接 3.3 CodeReview代码规范文档 四.最新项 ...

  9. 关闭jetbrains ide support 正在调试此浏览器提示

    1 安装JetBrains IDE Support插件 插件地址 2 启用插件 3 设置访问端口 4 WebStorm中设置Live Edit 5 关闭"JetBrains IDE Supp ...

  10. DevOps系列(1)-总体架构

    扯闲淡 在进入正式话题之前,先扯个淡,这算是第一篇我正式在博客上发布的随笔吧,之前也一直有想写点什么,将自己多年的工作经验分享出来,供大家参考点评,但是奈何一直对自己的文字功底不自信(其实也确实比较烂 ...