JAVAORM框架之Mybatis (Ibatis) 详解
Mybatis基础概念
Mybatis是一个持久层框架

它对JDBC操作数据库进行封装,让我们更关注SQL本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。下面是Mybatis的架构图

Mybatis又是如何解决JDBC中存在的问题呢?
1、 创建数据库连接相关操作,存在硬编码
a) 解决方案:通过Mybatis全局配置文件,对数据库连接进行配置
2、 statement相关操作,存在硬编码
a) 解决方案:通过Mapper映射文件,对statement相关处理进行配置。
3、 频繁开启数据库连接,会降低数据库处理性能。
a) 解决方案:通过Mybatis全局配置文件,配置连接池。
Mybatis开放方式演进



Mybatis框架核心要点
关联查询
所谓的关联查询就是一对一和一对多以及多对多的应用,例如下面的例子

一对一 : 例如在获取订单的时候需要获取该订单所属的用户信息
解决思路 : 使用ResultMap或者ResultType自定义一个POJO进行结果映射一对多 : 例如在获取用户信息的时候需要获取该用户的所有订单信息
解决思路 : 自定义一个POJO使用(只能使用)ResultMap进行结果映射
延迟加载(懒加载)
关于延迟加载
- MyBatis中的延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询。延迟加载可以有效的减少数据库压力。
- Mybatis的延迟加载,需要通过resultMap标签中的association和collection子标签才能演示成功。
- Mybatis的延迟加载,也被称为是嵌套查询,对应的还有嵌套结果的概念,可以参考一对多关联的案例。
- 注意:MyBatis的延迟加载只是对关联对象的查询有延迟设置,对于主加载对象都是直接执行查询语句的。
延迟加载分类
MyBatis根据对关联对象查询的select语句的执行时机,分为三种类型:直接加载、侵入式加载与深度延迟加载
- 直接加载: 执行完对主加载对象的select语句,马上执行对关联对象的select查询。
- 侵入式延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。但当要访问主加载对象的详情时,就会马上执行关联对象的select查询。即对关联对象的查询执行,侵入到了主加载对象的详情访问中。也可以这样理解:将关联对象的详情侵入到了主加载对象的详情中,即将关联对象的详情作为主加载对象的详情的一部分出现了。
- 深度延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。访问主加载对象的详情时也不会执行关联对象的select查询。只有当真正访问关联对象的详情时,才会执行对关联对象的select查询。
延迟加载策略需要在Mybatis的全局配置文件中,通过标签进行设置。
如何使用
直接加载 通过对全局参数:lazyLoadingEnabled进行设置,默认就是false。
<settings>
<!-- 延迟加载总开关 -->
<setting name="lazyLoadingEnabled" value="false"/>
</settings>
侵入式加载
<settings>
<!-- 延迟加载总开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 侵入式延迟加载开关 -->
<setting name="aggressiveLazyLoading" value="true"/>
</settings>
深度延迟加载
<settings>
<!-- 延迟加载总开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 侵入式延迟加载开关 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
动态SQL
动态SQL的思想:就是使用不同的动态SQL标签去完成SQL字符串的拼接处理。
解决的问题 :
- 在映射文件中,会编写很多有重叠部分的SQL语句,比如SELECT语句和WHERE语句等这些重叠语句,该如何处理
- 如果页面传递过来一个参数,但是SQL语句中的条件有多个,此时会发生问题。
主要标签
if标签 where标签 sql片段 foreach标签
Mybatis缓存
- Mybatis提供查询缓存,如果缓存中有数据就不用从数据库中获取,用于减轻数据压力,提高系统性能。
- Mybatis的查询缓存总共有两级,我们称之为一级缓存和二级缓存,如图:

• 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
• 二级缓存是Mapper(namespace)级别的缓存。多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
一级缓存原理图

第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息,将查询到的用户信息存储到一级缓存中。
如果中间sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
二级缓存原理图

1. 第一次调用mapper下的SQL去查询用户信息。查询到的信息会存到该mapper对应的二级缓存区域内。
2. 第二次调用相同namespace下的mapper映射文件中相同的SQL去查询用户信息。会去对应的二级缓存内取结果。
3. 如果调用相同namespace下的mapper映射文件中的增删改SQL,并执行了commit操作。此时会清空该namespace下的二级缓存。
如何开启二级缓存(默认关闭)
- 在核心配置文件SqlMapConfig.xml中加入以下内容(开启二级缓存总开关):
<!-- 开启二级缓存总开关 -->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
- 在UserMapper映射文件中,加入以下内容,开启二级缓存:
<!-- 开启本mapper下的namespace的二级缓存,默认使用的是mybatis提供的PerpetualCache -->
<cache></cache>
说明 : 由于二级缓存的数据不一定都是存储到内存中,它的存储介质多种多样,比如说存储到文件系统中,所以需要给缓存的对象执行序列化。如果该类存在父类,那么父类也要实现序列化。(既查询结果对象要实现序列化接口)
Mybatis逆向工程
由于Mybatis是半自动化的ORM框架,所以仍然有很多事情需要我们去做
例如 : 编写与数据库表对应的实体,编写Mapper接口,编写Mapper配置文件
所谓的Mybatis逆向工程仅仅是一个项目所以只需要在下面配置中填写好自己数据库的相关信息,运行main方法既可以为我们生成POJO类,Mapper接口,Mapper配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root" password="root">
</jdbcConnection>
<!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg"
userId="yycg" password="yycg"> </jdbcConnection> -->
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL
和 NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="com.kkb.ms.po"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.kkb.ms.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.kkb.ms.mapper" targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定数据库表 -->
<table schema="" tableName="user"></table>
<table schema="" tableName="order"></table>
</context>
</generatorConfiguration>
注意 :每次执行逆向工程代码之前,先删除原来已经生成的mapper xml文件再进行生成。mapper.xml文件的内容不是被覆盖而是进行内容追加,会导致mybatis解析失败。po类及mapper.java文件的内容是直接覆盖没有此问题。
PageHelper分页插件
如果你也在用Mybatis,建议尝试该分页插件,这个一定是最方便使用的分页插件。
使用方法如下
首先增加依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.6</version>
</dependency>
配置PageHelper
• Mybatis全局配置文件
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- config params as the following -->
<property name="helperDialect" value="mysql"/>
</plugin>
</plugins>
• Spring配置文件
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- other configuration -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!-- config params as the following -->
<value>
helperDialect=mysql
</value>
</property>
</bean>
</array>
</property>
</bean>
在项目中使用PageHelper
//获取第1页,10条内容,默认查询总数count
PageHelper.startPage(1, 10);
List<Country> list = countryMapper.selectAll();
//用PageInfo对结果进行包装
PageInfo page = new PageInfo(list);
//测试PageInfo全部属性
//PageInfo包含了非常全面的分页属性
assertEquals(1, page.getPageNum());
assertEquals(10, page.getPageSize());
注意事项
1. 需要分页的查询语句,必须是处于PageHelper.startPage(1, 10);后面的第一条语句。
2. 如果查询语句是使用resultMap进行的嵌套结果映射,则无法使用PageHelper进行分页。
Mybatis插件介绍
参考地址:https://www.cnblogs.com/fangjian0423/p/mybatis-interceptor.html
StatementHandler
ParameterHandler
ResultSetHandler
注解开发
使用注解开发,我们不再需要XML配置文件
常用注解说明
增删改查-静态SQL
- @Insert:相当于标签,实现新增
- @Update: 相当于标签,实现更新
- @Delete: 相当于标签,实现删除
- @Select: 相当于标签,实现查询
- @SelectKey:相当于标签,实现主键返回
增删改查-动态SQL
- @InsertProvider: 相当于标签,实现新增
- @UpdateProvider: 相当于标签,实现更新
- @DeleteProvider: 相当于标签,实现删除
- @SelectProvider: 相当于标签,实现查询
多表关联
• @Results: 相当于<resultMap>标签,需要和@Result注解一起使用。
• @Result: 相当于<result>和<id>标签,实现结果集中某一列的数据映射
* column 数据库的列名
* property 需要装配的属性名
* one 需要使用的@One 注解(@Result(one=@One()))
* many 需要使用的@Many 注解(@Result(many=@many()))
• @One: 相当于<association>标签,实现一对一关系映射
• @Many:相当于<collection>标签,实现一对多关系映射
• @One和@Many注解的属性:
* select 属性:代表将要执行的 sql 语句
* fetchType 属性:代表加载方式,一般如果要延迟加载都设置为 LAZY 的值
• 使用格式:
1. @Results({@Result(),@Result()})或@Results(@Result())
2. @Result(column=" ",property="",one=@One(select=""))
辅助注解
- @Options:相当于标签属性的设置
- @Param:如果你的映射器的方法需要多个参数,这个注解可以被应用于映射器的方法参数来给每个参数一个名字。
其他注解
- @CacheNamespace:相当于标签,实现二级缓存。
属性:implemetation,eviction,flushInterval,size,readWrite,blocking和properties
JAVAORM框架之Mybatis (Ibatis) 详解的更多相关文章
- ORM框架对比以及Mybatis配置文件详解
ORM框架对比以及Mybatis配置文件详解 0.数据库操作框架的历程 (1) JDBC JDBC(Java Data Base Connection,java数据库连接)是一种用于执行SQL语句 ...
- JavaORM框架之Mybatis篇(Ibatis)
欢迎查看Java开发之上帝之眼系列教程,如果您正在为Java后端庞大的体系所困扰,如果您正在为各种繁出不穷的技术和各种框架所迷茫,那么本系列文章将带您窥探Java庞大的体系.本系列教程希望您能站在上帝 ...
- 一、Mybatis配置详解
Mybatis配置详解 XML配置文件层次结构 下图展示了mybatis-config.xml的全部配置元素 properties元素 properties是一个配置属性的元素,让我们能在配置文件的上 ...
- Qt的Graphics-View框架和OpenGL结合详解
Qt的Graphics-View框架和OpenGL结合详解 演示程序下载地址:这里 程序源代码下载地址:这里 这是一篇纯技术文,介绍了这一个月来我抽时间研究的成果. Qt中有一个非常炫的例子:Boxe ...
- Scrapy框架的命令行详解【转】
Scrapy框架的命令行详解 请给作者点赞 --> 原文链接 这篇文章主要是对的scrapy命令行使用的一个介绍 创建爬虫项目 scrapy startproject 项目名例子如下: loca ...
- 框架基础学习之--详解web+maven+spring+mybatis+struts框架文件夹作用
详解web+maven+spring+mybatis+struts框架文件夹作用 1.程序名 2.Mybatis,mybatis是数据持久层,就是和对象类有关系的东西 3.存放java文件,xml,p ...
- MyBatis Generator 详解
MyBatis Generator中文文档 MyBatis Generator中文文档地址:http://mbg.cndocs.tk/ 该中文文档由于尽可能和原文内容一致,所以有些地方如果不熟悉,看中 ...
- MyBatis Generator 详解 【转来纯为备忘】
版权声明:版权归博主所有,转载请带上本文链接!联系方式:abel533@gmail.com 目录(?)[+] MyBatis Generator中文文档 运行MyBatis Generator X ...
- MyBatis Generator 详解(转)
MyBatis Generator中文文档 MyBatis Generator中文文档地址:http://mbg.cndocs.tk/ 该中文文档由于尽可能和原文内容一致,所以有些地方如果不熟悉,看中 ...
随机推荐
- Android开发学习笔记-SharedPreferences的用法
SharedPreferences介绍: 做软件开发应该都知道,很多软件会有配置文件,里面存放这程序运行当中的各个属性值,由于其配置信息并不多,如果采用数据库来存放并不划算,因为数据库连接跟操作等 ...
- golang-defer坑的本质
https://blog.csdn.net/hittata/article/details/77836435
- java获取map中的最小KEY,最小VALUE
import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map ...
- Java输出错误信息与调试信息
创建一个类,在该类的main()主方法中,使用System类中的out和err两个成员变量来完成调试与错误信息的输出. public class PrintErrorAndDebug { public ...
- Windows下切换盘符
方法: 直接输入盘符+引号,例如输入D:,不区分大小写. 使用cd命令,例如cd /d D: 使用cd命令有一些要注意的地方: 在同一个磁盘分区里,不需要加上\d,但是不同磁盘分区切换的时候,需要加上 ...
- Data Guard 主备库角色转换
1. switchover操作 1.1 备库先关闭实时日志应用 standby>alter database recover managed standby database cancel; 1 ...
- bodgeit测试平台
下载war安装包:https://code.google.com/archive/p/bodgeit/downloads http://resources.infosecinstitute.com/t ...
- U3D各键值说明
KeyCode :KeyCode是由Event.keyCode返回的.这些直接映射到键盘上的物理键. 值 对应键 Backspace 退格键 Delete Delete ...
- Spring Web 应用的最大败笔
开发人员在使用Spring应用是非常擅长谈论依赖注入的好处.不幸的是,他们不是那么真的利用它的好处,如单一职责原则,分离关注原则.如果我们一起来看看大部分Spring的Web应用程序,常见的错误的设计 ...
- linux 设置分辨率(转)
linux 设置分辨率 如果你需要在linux上设置显示屏的分辨率,分两种情况:分辨率模式存在与分辨率模式不存在,具体如下. 1,分辨率模式已存在 1)如何查询是否存在: 图形界面:在System S ...