MyBatis开发重点知识
1.1为什么需要ORM框架?
传统的JDBC编程存在的弊端:
ü 工作量大,操作数据库至少要5步;
ü 业务代码和技术代码耦合;
ü 连接资源手动关闭,带来了隐患;
MyBatis前身是iBatis,其源于“Internet”和“ibatis”的组合,本质是一种半自动的ORM框架,除了POJO和映射关系之外,还需要编写SQL语句;Mybatis映射文件三要素:SQL、映射规则和POJO;
1.2 MyBatis快速入门
步骤如下:
- 加入mybatis的依赖,版本3.5.x
- 添加mybatis的配置文件,包括MyBatis核心文件和mapper.xml文件
- 场景介绍:基于t_user表单数据查询、多数据查询;
- 编写实体类、mapper接口以及mapper xml文件;
- 编写实例代码:com.enjoylearning.mybatis.MybatisDemo. quickStart
核心类分析:
- SqlSessionFactoryBuilder:读取配置信息创建SqlSessionFactory,建造者模式,方法级别生命周期;
- SqlSessionFactory:创建Sqlsession,工厂单例模式,存在于程序的整个生命周期;
- SqlSession:代表一次数据库连接,一般通过调用Mapper访问数据库,也可以直接发送SQL执行, ;线程不安全,要保证线程独享(方法级);
- SQL Mapper:由一个Java接口和XML文件组成,包含了要执行的SQL语句和结果集映射规则。方法级别生命周期;
1. resultType还是resultMap?
2.1 resultType
resultType:当使用resultType做SQL语句返回结果类型处理时,对于SQL语句查询出的字段在相应的pojo中必须有和它相同的字段对应,而resultType中的内容就是pojo在本项目中的位置。
自动映射注意事项 :
- 前提:SQL列名和JavaBean的属性是一致的;
- 使用resultType,如用简写需要配置typeAliases (别名);
- 如果列名和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怎么样进行批量的操作
- 通过foreach动态拼装SQL语句
- 使用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 关联查询几个需要注意的细节
- 超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引;见《Java开发手册1.5》之5.2.2;
- 不得使用外键与级联,一切外键概念必须在应用层解决;见《Java开发手册1.5》之5.3.6;
- 字段允许适当冗余,以提高查询性能,但必须考虑数据一致;见《Java开发手册1.5》之5.1.13;
关联元素:association用于表示一对一关系,collection用于表示一对多关系;
关联方式:
ü 嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集
ü 嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型
8.2 一对一关联嵌套结果方式
association标签 嵌套结果方式 常用属性:
ü property :对应实体类中的属性名,必填项。
ü javaType :属性对应的 Java 类型 。
ü resultMap :可以直接使用现有的 resultMap ,而不需要在这里配置映射关系。
ü columnPrefix :查询列的前缀,配置前缀后,在子标签配置 result 的 column 时可以省略前缀
示例代码:com.enjoylearning.mybatis.testOneToOne.
开发小技巧:
- resultMap可以通过使用extends实现继承关系,简化很多配置工作量;
- 关联的表查询的类添加前缀是编程的好习惯;
- 通过添加完整的命名空间,可以引用其他xml文件的resultMap;
8.3 一对一关联嵌套查询方式
association标签 嵌套查询方式 常用属性:
ü select :另 一个映射查询的 id, MyBatis 会额外执行这个查询获取嵌套对象的结果 。
ü column :列名(或别名),将主查询中列的结果作为嵌套查询的参数。
ü fetchType :数据加载方式,可选值为 lazy 和 eager,分别为延迟加载和积极加载 ,这个配置会覆盖全局的 lazyLoadingEnabled 配置;
示例代码:com.enjoylearning.mybatis.testOneToOne().
嵌套查询会导致“N+1 查询问题”,导致该问题产生的原因:
- 你执行了一个单独的 SQL 语句来获取结果列表(就是“+1”)。
- 对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。
这个问题会导致成百上千的 SQL 语句被执行。这通常不是期望的。
解决“N+1 查询问题”的办法就是开启懒加载、按需加载数据,开启懒加载配置:
在<select>节点上配置“fetchType=lazy”
在MyBatis核心配置文件中加入如下配置:
<!-- 开启懒加载 ,当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。默认:true -->
<setting name="aggressiveLazyLoading" value="false" />
8.4 一对多关联
collection 支持的属性以及属性的作用和 association 完全相同。mybatis会根据id标签,进行字段的合并,合理配置好ID标签可以提高处理的效率;
开发小技巧:如果要配置一个相当复杂的映射,一定要从基础映射开始配置,每增加一些配置就进行对应的测试,在循序渐进的过程中更容易发现和解决问题 。
8.5 多对多关联
要实现多对多的关联,需要满足如下两个条件:
- 先决条件一:多对多需要一种中间表建立连接关系;
- 先决条件二:多对多关系是由两个一对多关系组成的,一对多可以也可以用两种方式实现;
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缓存调用过程
缓存的调用过程如下:
调用过程解读:
- 每次与数据库的连接都会优先从缓存中获取数据
- 先查二级缓存,再查一级缓存
- 二级缓存以namespace为单位的,是SqlSession共享的,容易出现脏读,建议避免使用二级缓存
- 一级缓存是SqlSession独享的,建议开启;
MyBatis开发重点知识的更多相关文章
- 【springmvc+mybatis项目实战】杰信商贸-6.重点知识回顾
1.重点知识回顾 Maven1)覆盖仓库文件,实际企业开发,公司会架一个测试服务器,在测试服务器中架私服.我们开发人员的程序,都连接私服.当本地没有项目中要使用的jar,Myeclipse maven ...
- Android开发重点难点1:RelativeLayout(相对布局)详解
前言 啦啦啦~博主又推出了一个新的系列啦~ 之前的Android开发系列主要以完成实验的过程为主,经常会综合许多知识来写,所以难免会有知识点的交杂,给人一种混乱的感觉. 所以博主推出“重点难点”系列, ...
- AJAX重点知识的心得体会
下面就为大家带来一篇 AJAX重点知识的心得体会.学习还是有点帮助的,给大家做个参考吧. AJAX是什么? 是Asynchronous Javascript And XML的首字母的缩写, 它不是一门 ...
- mybatis开发,你用 xml 还是注解?我 pick ...
最近在看公司项目时发现有的项目mybatis是基于注解开发的,而我个人的习惯是基于xml文件开发. 对于mybatis注解开发的原理理解不够,于是翻阅了部分源码,写下此文.主要介绍了mybatis开发 ...
- IOS开发基础知识碎片-导航
1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...
- 移动端 Web 开发前端知识整理
文章来源: http://www.restran.net/2015/05/14/mobile-web-front-end-collections/ 最近整理的移动端 Web 开发前端知识,不定期更新. ...
- MyBatis学习--mybatis开发dao的方法
简介 使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法. 主要概念介绍: MyBatis中进行Dao开发时候有几个重要的类,它们是SqlSessionFac ...
- 四 mybatis开发dao的方法
mybatis开发dao的方法 1.1 SqlSession使用范围 1.1.1 SqlSessionFactoryBuilder //以流的方式读取总的配置文件 Reader rea ...
- 【转载】STL"源码"剖析-重点知识总结
原文:STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点 ...
随机推荐
- java简单内存图
一 内存的分区 二 以数组为例画内存图 代码: class Demo01 { public static void main(String[] args) { //1.数据类型[] 数组名=new 数 ...
- 2020-06-16:Redis hgetall时间复杂度?
福哥答案2020-06-16: 时间复杂度是O(N).时间复杂度:O(N) where N is the size of the hash.
- C#算法设计排序篇之02-快速排序(附带动画演示程序)
快速排序(Quick Sort) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/677 访问. 快速排序由C. A. R ...
- Homekit_DoHome_智能通断器
本款通断器适用于IOS和android系统用户,苹果用户可以非常方便的使用siri进行有效控制,android用户需要下载Dohome App进行操作,同时支持市面上主流的智能音箱进行控制. 对于an ...
- 使用MIPS完成汇编程序——选择排序实现
题目: 从键盘输入10个无符号字数并从大到小进行排序,排序结果在屏幕上显示出来.要求能输入数字 和输出数字 且由大到小来排列 1.代码以及伪代码: 首先写出对应c++代码然后把c++代码翻译成汇编语言 ...
- 随机陷阱和P值
如果让大家写一个50次的抛硬币实验的可能结果(头像H或字T),多半人在连续三个一样的后,会换一下.因为大家都知道,连续一样的越多,概率越小,越不可能发生.大部分人不会去想,其实HHHTT和HHHHH发 ...
- Vue管理系统前端系列四组件拆分封装
目录 组件封装 首页布局拆分后结构 拆分后代码 状态管理中添加 app 模块 组件封装 在上一篇记录中,首页中有太多的代码,为了避免代码的臃肿,需要对主要的功能模块拆分,来让代码看起来更简洁,且能进行 ...
- 第3篇 Scrum 冲刺博客(专✌️团队)
目录 一.站立式会议 1.1 会议照片 1.2 成员完成情况 二.项目燃尽图 三.成员代码/文档签入记录 3.1 代码签入 3.2 Issue链接 3.3 CodeReview代码规范文档 四.最新项 ...
- 关闭jetbrains ide support 正在调试此浏览器提示
1 安装JetBrains IDE Support插件 插件地址 2 启用插件 3 设置访问端口 4 WebStorm中设置Live Edit 5 关闭"JetBrains IDE Supp ...
- DevOps系列(1)-总体架构
扯闲淡 在进入正式话题之前,先扯个淡,这算是第一篇我正式在博客上发布的随笔吧,之前也一直有想写点什么,将自己多年的工作经验分享出来,供大家参考点评,但是奈何一直对自己的文字功底不自信(其实也确实比较烂 ...