1.查询缓存
1.1什么是查询缓存
mybatis提供查询缓存,用于减轻数据压力,提高数据库性能mybatis提供一级缓存二级缓存一级缓存是SQLSession级别的缓存 在操作数据库时需要构造SQLSession对象,在对象中有一个数据结构(HashMap)用户存储缓存数据不同的SQLSession之间的缓存数据的区域(HashMap)是互不影响的。二级缓存是mapper级别的缓存 多个SQLSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是SQLSession的为什么要存储? 如果缓存中有数据就不用在从数据库中获取,大大提高系统的性能。1234567891011121314复制代码
2一级缓存
2.1一级缓存的工作原理 第一次发起查询用户id为1的用户的信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户 信息 得到用户信息,将用户信息存储到一级存储中 如果在SQLSession去执行commit操作(执行插入,更新,删除)清空SQLSession中的一级缓存。这样做的目的 为了缓存中永远存储的是最新的信息,避免脏读 第二次发起查询用户id为1的用户信息,先去查询缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取 用户信息 2.2一级缓存测试 mybatis默认支持一级缓存,不需要在配置文件去配置 按照上边一级缓存原理步骤测试12345678910111213复制代码
测试代码 public testCacher1() throws Exception{ SqlSession sqlSesssion=sqlSessionFactory.openSession();//创建代理对象 UserMapper userMapper=sqlSession.getMapper(UserMapper.class); //下边查询使用一个SqlSession //第一次发起请求,查询id为1的用户 User uyser=userMapper.findUserById(1); System.out.println(:user1); //如果SQLSession去执行commit操作(执行插入,更新,删除) 清空SQLSession中的一级缓存 这样做的目的是为了让缓存中存储的是最新的信息,避main脏读 //更新user的信息 user.setUsername(“测试用户22”); userMapper.updateUser(user1); //执行commint操作去清除缓存 SQLSession.commit(); //第二次发起请求,查询id为1的用户 User user2=username.fiondUserById(1); System.out.println(user2); sqlSession.close(); }123456789101112131415161718192021复制代码
2.3一级缓存的应用 正式开发,是将mybatis和spring进行整合开发,事务空载子service中 一个service方法中包括很多mapper方法调用 service //开始执行执行时,开启事务,创建SQLSession对象 //第一调用mapper的方法findUserByID(1); //第二次调用mapper的方法findUserByID(1);从一级缓存中取数据 //方法结束sqlSession关闭 如果是俩次service调用查询相同的用户信息,不走一级缓存,因为service方法结束,SQLSession就关闭 一级缓存就清空。 1234567891011复制代码
3.二级缓存
首先开启mybatis的二级缓存 SQLSession去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中 如果SQLSession去执行相同mapper下sql,执行commit提交,清空该mapper下的二级缓存区域的数据 SQLSession去查询用户id为1的用户信息,去缓存中查中是否存在数据,如果存在直接从缓存中取出数据 二级缓存与一级缓存区别:二级缓存的范围更大,多个SQLSession可以共享一个UserMapper二级缓存 UserMapper有一个二级缓存区域(按照namespace分),其他的mapper也有自己的缓存区域(按照namespace分) 每一个namespace的mapper有一个二级缓存区域,如果俩个mapper的namespace如果相同,这俩个 mapper执行sql查询到的数据就存在相同的二级缓存区域中3.1开启二级缓存12345678910复制代码
mybatis的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml 中开启二级缓存 二级缓存使用,需要在主文件中进行配置: ①启用二级缓存在UserMapper中开启二级缓存,UserMapper.xml下的sql执行完成会存储到它的缓存区域(HashMap)、 1234567891011复制代码
3.2调用pojo类实现序列化接口12复制代码
public class User implements Serializables{ private int id; private String username; private String sex; private Date birthday; private String address; }1234567复制代码
为了将缓存的数据取出执行序列化操作,因为二级缓存的存储介质多种多样,不一定在内存3.3测试方法1234复制代码
public testCacher2() throws Exception{ SqlSession sqlSesssion=sqlSessionFactory.openSession(); SqlSession sqlSesssion2=sqlSessionFactory.openSession(); SqlSession sqlSesssion3=sqlSessionFactory.openSession(); //创建代理对象 UserMapper userMapper=sqlSession.getMapper(UserMapper.class); //下边查询使用一个SqlSession //第一次发起请求,查询id为1的用户 User uyser=userMapper.findUserById(1); System.out.println(:user1); //这里执行关闭操作,将SQLSession中的数据写到二级缓存区域 SQLSession.close(); //使用SQLSession执行commit()操作 UserMapper userMapper3=sqlSession3.getMapper(UserMapper.class); User user=userMapper3.findUserById(1); user.setUsername(“测试用户22”); userMapper3.updateUser(user1); //执行commint操作去清除缓存 SQLSession3.commit(); SQLSession3.close(); UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class); //第二次发起请求,查询id为1的用户 User user2=userMapper2.findUserById(1); Stystem.out.println(user2); sqlSession2.close(); }123456789101112131415161718192021222324252627282930313233复制代码
3.4useCache配置 ①.设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。
public interface Cache{ String getId(); void putObject(Object key ,Object value); Object getObject(Object key); } mybatis默认实现的cache类是 public class PerpetualCache implements Cache{ private String id; private Map
4.3配置信息12复制代码
配置mapper中的cache中的type为ehcache对cache接口的实现1234567复制代码
3.4加入ehcache包 ehcache-core-2.6.5.jar mybatis-ehcache-1.0.2jar 3.5加入ehcache的配置文件123456复制代码
在classpath下配置 13 123456789101112131415复制代码4 13 14
属性说明: diskStore:指定数据在磁盘中的存储位置。 defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用指定的的管理策略 以下属性是必须的: maxElementsInMemory - 在内存中缓存的element的最大数目 maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大 eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断 overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上 以下属性是可选的: timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大 timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大 diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区. diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。 diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作 memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出 4二级缓存应用场景 应用场景:123456789101112131415161718复制代码
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访
问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时 间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。5.局限性: mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。复制代码