spring对象管理和mybatis一级缓存
Posted 浴盆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring对象管理和mybatis一级缓存相关的知识,希望对你有一定的参考价值。
控制反转
控制什么?控制bean的创建和销毁(生命周期),反转什么,把bean的生命周期交给ioc容器。开车回家,创建一辆车,车对象左转,车对象右转
最后销毁车辆。人对象有goHome、goShop等方法,这些需要依赖车对象,如果在人的类里面创建一辆车的对象,如果车要换,所有上层应用都要感知。
实现控制反转
被依赖的bean需要优先创建,同时还需要:
- 实例化bean
- 保存bean
- 提供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一级缓存的主要内容,如果未能解决你的问题,请参考以下文章