关于Mybatis、缓存、延迟加载、执行流程、一篇搞定

目录

1.Mybatis一级缓存

2.Mybatis二级缓存

3.Mybatis执行流程

4.Mybatis延迟加载

 1.Mybatis一级缓存

先说一级缓存和二级缓存的关系及区别:

Mybatis缓存其实也是一种减少数据库IO操作的技术手段,这个缓存存储在本地的一个类似于HashMap当中

其中一级缓存默认是开启的,就是说第一次查询出的结果会被缓存到本地他的作用域是同一个sqlSession,方便同一会话内的查询复用

而二级缓存是跨SqlSession的,开启后可将一级缓存数据复制到二级缓存,提升数据共享性。两种缓存都会在增删改操作后被清除,一级缓存的数据会在SqlSession提交或关闭时转移到二级缓存。

《======================================================================》

看到这张图是不是很熟悉呢,没错缓存!一个我们Java程序员耳熟能详的东西,说白了就是在数据库前面挡住一层不直接去查数据库减少IO。那么我们今天说的关于Mybatis的缓存也是这个作用。

我们先说一级缓存,一级缓存基于本地缓存也称之为PerpetualCache 其实就是个HashMap,其存储作用域为 Session,当Session进行flush(刷新)或close(释放)之后,该Session中的所有缓存就将清空,默认打开一级缓存

我们看代码,我们获取一个sqlSession用它来执行SQL,然后获取UserMapper接口的代理对象UserMapper然后查询ID为6的数据,两次查询结果我来告诉大家,只执行了一次SQL操作只查询了一次数据库,也就是说我们第二次去查询ID为6的数据走了第一次查询的缓存,那么这个缓存的作用域就是同一个sqlSession。

//2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 执行sql
//3.1 获取UserMapper接口的代理对象UserMapper userMapper1=sqlSession.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
User user = userMapper1.selectById(6);
System.out.println(user);
System.out.println("---------------------");
User user1 = userMapper2.selectById(6);
System.out.println(user1);

2.Mybatis二级缓存

二级缓存是基于namespace(命名空间)和mapper的作用域起作用的,不是依赖于SQL session,默认也是采用 PerpetualCache HashMap 存储

我们看代码创建了两个sqlSession,打印结果我告诉大家,查询了两次数据库,也就是局限在了一级缓存作用域Session中

//2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession1 = sqlSessionFactory.openSession();
//3. 执行sql
//3.1 获取UserMapper接口的代理对象
UserMapper userMapper1 =sqlSession1.getMapper(UserMapper.class);

User user1 = userMapper1.selectById(6);
System.out.println(user1);
sqlSession1.close();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
System.out.println("---------------------");
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
User user2 = userMapper2.selectById(6);
System.out.println(user2);
//4.关闭资源
sqlSession2.close();

现在我们打开二级缓存(默认是关闭的)

开启方式,两步:

1.全局配置文件

<settings>
    <setting name="cacheEnabled" value="true
</settings>

2.映射文件

使用<cache/>标签让当前mapper生效二级缓存

这样二级缓存就生效了,在打印时就只查询了一次缓存

二级缓存注意事项

1,对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了新增、修改、删除操作后,默认该作用域下所有 select 中的缓存将被 clear(意思就是缓存是需要更新的,保证数据的一致性,那么只要当有新增修改删除操作,缓存就会被删除)

2,二级缓存需要缓存的数据实现Serializable接口

3,只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中(意思就是只有第一个sqlSession 进行刷新(flush)或者清除(close))缓存的数据才会同步到二级缓存

3.Mybatis执行流程

①读取MyBatis配置文件:mybatis-config.xml加载运行环境和映射文件

②构造会话工厂SqlSessionFactory,一个项目只需要一个,单例的,一般由spring进行管理

③会话工厂创建SqlSession对象,这里面就含了执行SQL语句的所有方法

④操作数据库的接口,Executor执行器,同时负责查询缓存的维护

⑤Executor接口的执行方法中有一个MappedStatement类型的参数,封装了映射信息

⑥输入参数映射

⑦输出结果映射

4.Mybatis延迟加载

延迟加载的意思是:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据,比如现在有两张表,用户表、订单表,一个用户可以有多个订单也就是一对多关系,体现到延迟加载就是,查询用户的时候,把用户所属的订单数据也查询出来这个是立即加载,查询用户的时候暂时不查询订单数据,当需要订单的时候,再查询订单,这个就是延迟加载。Mybatis支持一对一关联对象和一对多关联集合对象的延迟加载。

具体实现

其实说白了就是在执行一对多SQL时,需要把用户表和对应订单表的数据集合查询出来,那么就先判断一下查询集合的SQL是否为空,如果为空就去查询出来,然后在set进去,最后完成。

1. 使用CGLIB创建目标对象的代理对象

2. 当调用目标方法user.getOrderList()时,进入拦截器invoke方法,发现user.getOrderList()是null值,执行sql查询order列表

3. 把order查询上来,然后调用user.setOrderList(List<Order> orderList) ,接着完成user.getOrderList()方法的调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值