spring对象管理和mybatis一级缓存

Posted 浴盆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring对象管理和mybatis一级缓存相关的知识,希望对你有一定的参考价值。

控制反转

控制什么?控制bean的创建和销毁(生命周期),反转什么,把bean的生命周期交给ioc容器。开车回家,创建一辆车,车对象左转,车对象右转
最后销毁车辆。人对象有goHome、goShop等方法,这些需要依赖车对象,如果在人的类里面创建一辆车的对象,如果车要换,所有上层应用都要感知。

实现控制反转

被依赖的bean需要优先创建,同时还需要:

  1. 实例化bean
  2. 保存bean
  3. 提供bean,每个bean都有一个id对应

可以使用一个conCurrentHashMap来保存创建的bean,每个bean通过唯一的beanId来标识,作为map的key

setBean(Class<?> clazz, String beanId, String... parentBeanIds) 
  Object[] paramValues = new Object[parentBeanIds.length]
  // 循环beans
  paramValues[i] = beans.get(parentBeanIds[i])
  // 所有被依赖的bean通过构造方法注入
  bean = clazz.getConstructors().newInstance(paramValues)
  beans.put(beanId, bean)

在spring中可以使用ApplicationContext进行实例化xml声明的bean,xml中可以使用factory-method和factory-bean定义生产bean的类。注入bean参数可以使用constructor标签进行注入构造函数参数注入。

mybatis一级缓存

不使用缓存的时候,client通过mybatis的executor直连数据库,如果使用缓存,中间会增加一个cache层。mybatis基本配置由environments标签来声明数据库连接,通过mappers标签来声明具体的mapper数据库语句。
证明一级缓存存在

SqlSession sqlSession = sqlSessionFactory.openSession();
TempEntity tempEntity1 =  sqlSession.selectOne("com.alibaba.test.getById", 1);
TempEntity tempEntity2 =  sqlSession.selectOne("com.alibaba.test.getById", 1);
logger.info(tempEntity1==tempEntity2);

结果为true,说明存在一级缓存,并且默认开启。第一次读取数据库之后,mybatis将结果写入缓存中。那么mybatis怎么判断两次查询是完全相同的查询来判断是否命中缓存?总共有5层判断,第一层判断是mapper中定义的id

<select id="getById" parameterType="int" resultType="pointAsset"></select>
<select id="getById2" parameterType="int" resultType="pointAsset"></select>

如果id不相同,则判断非相同查询,即使两个查询语句、参数等完全一样。第二层判断是查询的参数:

TempEntity tempEntity1 =  sqlSession.selectOne("com.alibaba.test.getById", 1);
TempEntity tempEntity2 =  sqlSession.selectOne("com.alibaba.test.getById", 2);

参数不同,则非相同查询,如果参数传入是map,则只判断最终sql中的参数相同即可。第三个条件是分页参数必须相同,这个使用较少。第四个条件是sql语句文本必须相同(两个sql语句语义相同,比如where 1=1,无法通过校验)。第五个条件是数据库连接环境,通过environments标签声明的环境

mybatis一级缓存生命周期

mybatis的生命周期是在数据库事务的生命周期之内。不同事务间缓存隔离。未开启事务,每次请求都会关闭旧的session开启新的session,此时一级缓存无效。如果开启事务,在一个事务内,spring通过threadlocal始终使用同个session,此时一级缓存在事务内有效。
缓存生成:使用update方法无法生成缓存

// 生成缓存
sqlSession.select
// 不使用缓存
sqlSession.update

sqlSession commit、rollback和关闭的时候会清空缓存。如何验证此时缓存清空,可以通过反射的getClass().getDeclaredField方法来找到存储的缓存的map,看是否被清空
同时,在执行delete/update/insert后,缓存会被清空。
也可以通过sqlSession的clearCache手动进行清除

以上是关于spring对象管理和mybatis一级缓存的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis一级缓存和二级缓存总结

mybatis一级缓存和二级缓存

MyBatis 缓存

MyBatis缓存

Mybaits 缓存

Mybatis和mybatis-spring一级缓存