Mybatis 加载策略及注解开发
加载策略
什么是延迟加载
延迟加载就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载。
举个栗子
- 在一对多中,当我们有一个用户,它有个100个订单
在查询用户的时候,要不要把关联的订单查出来?
在查询订单的时候,要不要把关联的用户查出来? - 回答:
在查询用户时,用户下的订单应该是,什么时候用,什么时候查询。
在查询订单时,订单所属的用户信息应该是随着订单一起查询出来。
延迟加载的优缺点
-
优点:
先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。 -
缺点:
因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降 -
在多表中:
一对多,多对多:通常情况下采用延迟加载
一对一(多对一):通常情况下采用立即加载 -
注意
延迟加载是基于嵌套查询来实现的
局部延迟加载
设置延迟加载
大家在配置了延迟加载策略后,发现即使没有调用关联对象的任何方法,但是在你调用当前对象的 equals、clone、 hashCode、 toString
方法时也会触发关联对象的查询。
我们可以在配置文件中使用 lazyLoadTriggerMethods
配置项覆盖掉上面四个方法。
<settings>
<!-- 下面所有方法都会进行延迟加载 -->
<setting name="lazyLoadingEnabled" value="toString()"/>
</settings>
全局延迟加载
在 mybatis 的核心配置文件中可以使用 setting标签修改全局的加载策略。
<!-- 开启全局延迟加载 -->
<setting name="lazyLoadTriggerMethod" value="true"/>
- 注意:
局部的加载策略优先级高于全局的加载策略。
Mybatis缓存
为什么使用缓存?
当用户频繁查询某些固定的数据时第一次将这些数据从数据库中查询岀来保存在缓存中。当用户再次查询这些数据时不用再通过数据库查询而是去缓存里面查询。减少网络连接和数据库查询带来的损耗,从而提高我们的查询效率减少高并发访问带来的系统性能问题。
一句话概括:经常查询一些不经常发生变化的数据,使用缓存来提高查询效率。
像大多数的持久化框架—样, Mybatis也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。 Mybatis中缓存分为一级缓存,二级缓存。
一级缓存
介绍
一级缓存是 Sqlsession 级别的缓存,是默认开启的。
所以在参数和SQL完全一样的情况下,我们使用同一个 SqlSession对象调用个 Mapper方法,往往只执行一次SQL,因为使用 Selsession第一次查询后MyBatis会将其放在缓存中,以后再查词的时候,如果没有声明需要刷新,并且缓存没有超时的情况下, SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。
分析
一级缓存是 SqlSession 范围的缓存,执行 SqlSession 的C(增加)、U(更新)、D(删除)操作,或者调用 clearCache()、 commit()、close()方法,都会清空缓存。
二级缓存
不建议使用 Mybatis 的二级缓存,容易出现严重的脏读问题。实际使用中弊大于利,比较鸡肋。开发中我们一般会使用 Redis 来做第三方缓存。
介绍
二级缓存是 namespace 级别(跨 sqlSession)的缓存,是默认不开启的。
二级缓存的开启需要进行配置,实现二级缓存的时候, MyBatis要求返回的POJO必须是可序列化的。也就是要求实现 Serializable 接口,配置方法很简单,只需要在映射 XML 文件配置<cache />
就可以开启二级缓存了。
开启二级缓存
- 配置核心配置文件
<!-- 开启二级缓存 cacheEnabled 的默认值为 true,可以忽略配置,为了规范性所以写上。 -->
<setting name="cacheEnabled" value="true"/>
- 在 UserMapper.xml 中添加
<cache/>
标签 即开启二级缓存。 - 可以给某个 sql 增加
useCache=false
不使用二级缓存。
分析
二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mappe r映射的 sql 语句,多个 SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。
1.映射语句文件中的所有 select 语句将会被缓存。
2.映射语句文件中的所有 Insert、 update 和 delete 语句会刷新缓存。
MyBatis注解
Mybatis常用注解
@Insert:实现新增,代替了<insert></insert>
@Delete:实现刪除,代替了<delete></delete>
@Update:实现更新,代替了<update></update>
@Select:实现查询,代了< select></select>
@Result:实现结果集封装,代了<result></result>
@Results:可以与@Result一起使用,封装多个结果集,代替了<resultMap></resultMap>
@one:实现一对一结果集封装,代替了<association></association>
@Many:实现一对多结果集封装,代替了<collection></collection>
Mybatis注解的增删改查
创建 UserMapper接口
使用注解实现复杂映射开发
之前我们在映射文件中通过配置<resultMap>、<association>、<collection>
来实现复杂关系映射。使用注解开发后,我们可以使用@Reu1ts、@Result、@one、@Many
注解组合完成复杂关系的配置
注解延迟加载
不管是一对一还是一对多,在注解配置中都有 fetchTypel的属性
fetchType = FetchType.LAZY# Mybatis 加载策略及注解开发
# 加载策略
## 什么是延迟加载
> 延迟加载就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载。
举个栗子
- 在一对多中,当我们有一个用户,它有个100个订单
在查询用户的时候,要不要把关联的订单查出来?
在查询订单的时候,要不要把关联的用户查出来?
- 回答:
在查询用户时,用户下的订单应该是,什么时候用,什么时候查询。
在查询订单时,订单所属的用户信息应该是随着订单一起查询出来。
## 延迟加载的优缺点
- 优点:
先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
- 缺点:
因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降
- 在多表中:
一对多,多对多:通常情况下采用延迟加载
一对一(多对一):通常情况下采用立即加载
- 注意
延迟加载是基于嵌套查询来实现的
## 局部延迟加载
![image](https://img2020.cnblogs.com/blog/2354934/202109/2354934-20210925171133428-1970102745.png)
## 设置延迟加载
大家在配置了延迟加载策略后,发现即使没有调用关联对象的任何方法,但是在你调用当前对象的 `equals、clone、 hashCode、 toString`方法时也会触发关联对象的查询。
我们可以在配置文件中使用 `lazyLoadTriggerMethods`配置项覆盖掉上面四个方法。
```xml
<settings>
<!-- 下面所有方法都会进行延迟加载 -->
<setting name="lazyLoadingEnabled" value="toString()"/>
</settings>
全局延迟加载
在 mybatis 的核心配置文件中可以使用 setting标签修改全局的加载策略。
<!-- 开启全局延迟加载 -->
<setting name="lazyLoadTriggerMethod" value="true"/>
- 注意:
局部的加载策略优先级高于全局的加载策略。
Mybatis缓存
为什么使用缓存?
当用户频繁查询某些固定的数据时第一次将这些数据从数据库中查询岀来保存在缓存中。当用户再次查询这些数据时不用再通过数据库查询而是去缓存里面查询。减少网络连接和数据库查询带来的损耗,从而提高我们的查询效率减少高并发访问带来的系统性能问题。
一句话概括:经常查询一些不经常发生变化的数据,使用缓存来提高查询效率。
像大多数的持久化框架—样, Mybatis也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。 Mybatis中缓存分为一级缓存,二级缓存。
一级缓存
介绍
一级缓存是 Sqlsession 级别的缓存,是默认开启的。
所以在参数和SQL完全一样的情况下,我们使用同一个 SqlSession对象调用个 Mapper方法,往往只执行一次SQL,因为使用 Selsession第一次查询后MyBatis会将其放在缓存中,以后再查词的时候,如果没有声明需要刷新,并且缓存没有超时的情况下, SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。
分析
一级缓存是 SqlSession 范围的缓存,执行 SqlSession 的C(增加)、U(更新)、D(删除)操作,或者调用 clearCache()、 commit()、close()方法,都会清空缓存。
二级缓存
不建议使用 Mybatis 的二级缓存,容易出现严重的脏读问题。实际使用中弊大于利,比较鸡肋。开发中我们一般会使用 Redis 来做第三方缓存。
介绍
二级缓存是 namespace 级别(跨 sqlSession)的缓存,是默认不开启的。
二级缓存的开启需要进行配置,实现二级缓存的时候, MyBatis要求返回的POJO必须是可序列化的。也就是要求实现 Serializable 接口,配置方法很简单,只需要在映射 XML 文件配置<cache />
就可以开启二级缓存了。
开启二级缓存
- 配置核心配置文件
<!-- 开启二级缓存 cacheEnabled 的默认值为 true,可以忽略配置,为了规范性所以写上。 -->
<setting name="cacheEnabled" value="true"/>
- 在 UserMapper.xml 中添加
<cache/>
标签 即开启二级缓存。 - 可以给某个 sql 增加
useCache=false
不使用二级缓存。
分析
二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mappe r映射的 sql 语句,多个 SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。
1.映射语句文件中的所有 select 语句将会被缓存。
2.映射语句文件中的所有 Insert、 update 和 delete 语句会刷新缓存。
MyBatis注解
Mybatis常用注解
@Insert:实现新增,代替了<insert></insert>
@Delete:实现刪除,代替了<delete></delete>
@Update:实现更新,代替了<update></update>
@Select:实现查询,代了< select></select>
@Result:实现结果集封装,代了<result></result>
@Results:可以与@Result一起使用,封装多个结果集,代替了<resultMap></resultMap>
@one:实现一对一结果集封装,代替了<association></association>
@Many:实现一对多结果集封装,代替了<collection></collection>
Mybatis注解的增删改查
创建 UserMapper接口
使用注解实现复杂映射开发
之前我们在映射文件中通过配置<resultMap>、<association>、<collection>
来实现复杂关系映射。使用注解开发后,我们可以使用@Reu1ts、@Result、@one、@Many
注解组合完成复杂关系的配置
注解延迟加载
不管是一对一还是一对多,在注解配置中都有 fetchTypel的属性
fetchType = FetchType.LAZY 表示懒加载
fetchType = FetchType.EAGER 表示立即加载
fetchType = FetchType.DEFAULT 表示使用全局配置
小结
注解开发和 xml 配置优劣分析
- 注解开发和xm配置相比,从开发效率来说,注解编写更简单,效率更高。
- 从可维护性来说,注解如果要修改,必须修改源码,会导致维护成本增加。xml维护性更强。
表示懒加载
fetchType = FetchType.EAGER 表示立即加载
fetchType = FetchType.DEFAULT 表示使用全局配置
注解开发和 xml 配置优劣分析
1. 注解开发和xm配置相比,从开发效率来说,注解编写更简单,效率更高。
2. 从可维护性来说,注解如果要修改,必须修改源码,会导致维护成本增加。xml维护性更强。