缓存(mybatis)
来源:互联网 发布:dts音效软件 编辑:程序博客网 时间:2024/04/30 12:44
1.什么是查询缓存:
mybaitis也提供了查询缓存,用于减少数据库访问次数,提高了数据库的性能而存在的一种机制。有一级、二级缓存。
一级缓存:操作数据库时,会操作会话SqlSession对象,在会话对象中有个内存(数据结构HashMap),用于存储缓存数据。
不同的SqlSession他们之间的缓存数据区域是互补影响的。
二级缓存:Mapper级别的缓存,多个SqlSession去操作同一个Mapper的SQL语句。多个SQLSession操作数据库所得到数据会存储在二级缓存区域,可以共用二级缓存,二级缓存是跨SqlSession的。
一级缓存:
第一次发起查询用户id为1的用户信息,先去缓存中找是否有id为1的用户信息,如果没有,会到数据库中查询出来,并存储到一级缓存中。
如果在第一次查询和第二次查询中间有操作事务操作,一级缓存里的数据被自动清空。如果不清除,第二次查询到的还是第一次的数据。为了让缓存中永远存储最新的查询数据,也就是为了避免脏数据。
第二次发起查询用户id为1的用户信息,先去缓存中找是否有id为1的用户信息,查到有,会直接返回出来。
缓存的作用:如果缓存中有需要查询的数据,就不需要去数据库中查找,减少对数据库的访问。
一级缓存测试:
mybaitis和hibernate一样默认开启一级缓存,无须配置。
按照上面一级缓存原理去进行测试。
/** * 首先说明一点,一级缓存就是SqlSession级别的缓存 * 一级缓存工作原理:第一次查询的时候,会先去sqlSessionX的缓存查询数据是否存在, * 不存在去数据库查,查到放入sqlSessionX缓存。第二次查同一个ID的数据时,还是先去sqlSessionX缓存找,找到就返回出来。 */public static void testcache1(){SqlSession sqlSessionX = MybaitisUtil.getSQLSession(); UserMapper userMapper = sqlSessionX.getMapper(UserMapper.class); User user1 = userMapper.selectByuid(1); System.out.println(user1);User user2 = userMapper.selectByuid(2);//其他IDSystem.out.println(user2);User user3 = userMapper.selectByuid(1);System.out.println(user3); Mybatis.close(sqlSessionX);//关闭之后,再次创建依然是先去session找,肯定没有,去数据库查找数据。 }
打印结果:
public static void testcache1(){ SqlSession sqlSessionX = MybaitisUtil.getSQLSession(); UserMapper userMapper = sqlSessionX.getMapper(UserMapper.class); User user1 = userMapper.selectByuid(1); System.out.println(user1); //进行事务操作 user1.setUsername("zhangsan"); userMapper.updateuser(user1); sqlSessionX.commit(); //提交事务后,在缓存中的数据会被自动清除。所以,下面的查询会再次去数据库查询。 User user2 = userMapper.selectByuid(1); System.out.println(user2); Mybatis.close(sqlSessionX);}打印结果:
在spring和mybaitis的开发中,事务控制在Service层,一个Service包括了多个mapper的调用,
Service{
//开始执行时,开启事务,创建SqlSession对象,
//第一次调用mapper.findbyId(1);
//第二次调用mapper.findbyId(1);//从一级缓存读取,
//方法结束,SqlSession关闭。
}
如果是执行多次service调用查询相同用户信息,不会搞这个一级缓存,因为SqlSession方法结束,SqlSession就关闭,一级缓存当然就清空!所以,需要使用二级缓存(mapper级别的缓存)。
SqlSession1去查询id为1的用户信息,查询到的用户信息会将查询数据存储到二级缓存。
如果SqlSession3去执行相同mapper下的sql,执行commit提交,清空该mapper下的二级缓存区域的数据。
SqlSession2去查询id为2的用户信息,去缓存中查找,是否存在数据,如果存在直接从二级缓存中取出数据。
二级缓存和一级缓存的区别,二级缓存的范围大,多个sqlsession可以共享一个UserMapper的二级缓存区域。
UserMapper有一个二级缓存区域(按照namespace分)其他也有自己的缓存区域。
每一个namespace的mapper都有一个二级缓存区域,两个mapper的namespace如果相同,那么查询到的数据就会放在同一个二级缓存中。
mybatis的二级缓存的准备工作:
1、mybatis-config.xml 添加:<setting name="cacheEnabled" value="true"/>
2、Usermapper.xml 添加:<cache/>
3、pojo需要序列化。
测试代码:
/** * 二级缓存测试: * 二级缓存是mapper级别的缓存,创建三个usermapper对象, * 第一个usermapper去二级缓存查看数据,没有找到去数据库查找,将数据存储在二级缓存内,第二个usermapper首先会去二级缓存,找到将值返回。 * 如果中间有事务操作,会清空缓存。 */public static void testcache2(){SqlSession sqlSession1 = MybaitisUtil.getSQLSession();SqlSession sqlSession2 = MybaitisUtil.getSQLSession();SqlSession sqlSession3 = MybaitisUtil.getSQLSession();SqlSession sqlSession4 = MybaitisUtil.getSQLSession(); UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class); System.out.println(userMapper1.selectByuid(1)); sqlSession1.close(); UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class); System.out.println(userMapper2.selectByuid(1)); sqlSession2.close(); //事务操作 UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class); User user = userMapper3.selectByuid(1); user.setUsername("李四"); userMapper3.updateuser(user); sqlSession3.commit();//整个UsernMapper缓存被清空 sqlSession3.close(); UserMapper userMapper4 = sqlSession4.getMapper(UserMapper.class); System.out.println(userMapper4.selectByuid(1)); sqlSession4.close(); }打印结果:
每次查询如果需要最新数据,需要禁用二级缓存:在mapper.xml上可以添加useCache="false"。
<!--查询需要: 输入的映射参数类型parameterType=int,输出映射参数类型resultType=User 是最终查询结果的数据类型--> <select id="selectByuid" parameterType="int" resultType="user" useCache="false"> <!-- useCache="false" 禁用二级缓存 --> select * from user where id=#{id} </select>
public static void testcache2(){SqlSession sqlSession1 = MybaitisUtil.getSQLSession();SqlSession sqlSession2 = MybaitisUtil.getSQLSession();SqlSession sqlSession3 = MybaitisUtil.getSQLSession();SqlSession sqlSession4 = MybaitisUtil.getSQLSession(); UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class); System.out.println(userMapper1.selectByuid(1)); sqlSession1.close(); UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class); System.out.println(userMapper2.selectByuid(1)); sqlSession2.close(); //事务操作// UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);// User user = userMapper3.selectByuid(1);// user.setUsername("李四");// userMapper3.updateuser(user);// sqlSession3.commit();// sqlSession3.close(); UserMapper userMapper4 = sqlSession4.getMapper(UserMapper.class); System.out.println(userMapper4.selectByuid(1)); sqlSession4.close(); }
打印结果:
2.分布式缓存:
如图:现在又服务器1和服务器2。用户向服务器1请求数据查询,把缓存存储在服务器1,当用户请求到服务器2的时候,发现并没有缓存,这就是一个很尴尬的事情。
mybatis需要和其他框架整合,对缓存数据进行集中管理。
为了系统的性能提升,对缓存数据进行集中的管理,使用分布式缓存。
3.应用场景和局限性
对于访问多的查询请求且用户查询结果实时性不高,此时可以采用mybatis二级缓存技术降低数据库的访问量,业务场景:耗时较高的统计分析Sql,电话账单查询sql等等,
通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushinterval,比如30分钟一小时24小时。
mybaitis二级缓存粒度的数据级别缓存实现不好,比如:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品,此时就无法满足刷新当前商品信息,而不刷新其他商品,因为mybatis的二级缓存是以mapper位单位的,解决这种问题需要在业务层根据需求对数据库有针对性缓存。
- 缓存(mybatis)
- 【Mybatis框架】查询缓存(一级缓存)
- MyBatis缓存技术(一级缓存、二级缓存)
- MyBatis之缓存(一级缓存、二级缓存)
- mybatis 缓存(一) 一级缓存
- mybatis缓存问题(一)
- mybatis(11) 查询缓存
- mybatis 缓存(二) 二级缓存
- Mybatis 缓存(一二级缓存)
- mybatis缓存(二)+redis
- mybatis--()缓存整合ehcache
- MyBatis-缓存
- MyBatis 缓存
- mybatis缓存
- mybatis缓存
- MyBatis 缓存
- mybatis 缓存
- mybatis缓存
- 在win上开发scala所遇到的坑
- Hook
- Linux -mv命令的10个实用例子
- 为什么Java中没有sizeof()
- Bibtex Item for RFC files
- 缓存(mybatis)
- webpack英文文档阅读--图片的处理
- Node.js 路由
- 现在Java web什么框架比较好
- Genymotion 下载镜像速度慢的解决办法
- Unity控制在面板上显示变量
- 代码查看完整崩溃日志
- Win7下安装CetOS 7
- 编码实现Cohen-Sutherland端点编码算法