来源:blog.csdn.net/qq_38245668/article/details/1058032981,MyBatis缓存介绍Mybatis提供了对缓存的支持,但是默认情况下没有配置,只开启一级缓存,二级缓存缓存需要手动打开。一级缓存只是相对于同一个SqlSession。即对于同一个事务,多次执行同一个Mapper的同一个查询方法。第一次查询后,MyBatis会将查询结果放入缓存中,中间不涉及对应Mapper的数据更新(Insert、Update、Delete)操作。接下来,后续查询将从缓存中获取,而不查询数据库。二级缓存是针对应用级缓存的,也就是针对不同的SqlSession。当启用二级缓存时,MyBatis会将第一个查询结果存储在全局缓存中,供Mapper使用。如果中间没有进行Mapper的数据更新操作,那么后续相同的查询都会从缓存中获取。2.二级缓存问题根据二级缓存的介绍,发现如果Mapper只是单表查询,是不会有问题的,但是如果Mapper中涉及的查询有一个联合表查询,比如UserMapper在查询用户信息时需要关联查询组织信息,即用户表需要关联组织表。OrganizationMapper在执行更新时不会更新UserMapper的缓存。这样一来,在使用UserMapper使用相同条件查询用户信息时,会等待组织信息没有更新,造成数据不一致的情况。2.1.数据不一致问题验证查询SQLSELECTu.*,o.nameorg_nameFROMuseruLEFTJOINorganizationoONu.org_id=o.idWHEREu.id=#{userId}UserMapperUserInfoqueryUserInfo(@Param("userId")StringuserId);UserServicepublicUserEntityqueryUser(StringuserId){UserInfouserInfo=userMapper.queryUserInfo(userId);returnuserInfo;}调用查询得到查询结果(多次查询得到缓存数据),其中userId=1,data为用户查询结果{"code":"1","message":null,"data":{"id":"1","username":"admin","password":"admin","orgName":"Organization1"}}查询对应的组织信息,结果{"code":"1","message":null,"data":{"id":"1","name":"Organization1"}}发现与用户缓存数据一致。执行更新组织操作,将组织1更改为组织2,再次查询组织信息{"code":"1","message":null,"data":{"id":"1","name":"Organization2"}}再次查询用户信息,发现{"code":"1","message":null,"data":{"id":"1","username":"admin"还是obtainedfromcache","password":"admin","orgName":"Organization1"}}出现这个问题的原因是组织数据信息的更新只会更新Mapper对应的缓存数据,而不会通知一些Mapper更新关联表组织对应的缓存数据2.2.问题解决思路在定义Mapper1时,手动配置对应的关联Mapper2,实例化Mapper1缓存cache1时,读取关联Mapper2的cache2相关信息。cache1中cache2的引用信息,当cache1执行clear时,同步操作cache2执行clear3,关联缓存刷新开启二级缓存,本地项目使用MyBatisPlusmybatis-plus.configuration.cache-enabled=true主要使用自定义注解CacheRelations,自定义缓存实现RelativeCache和缓存上下文RelativeCacheContext。注解CacheRelations,使用时需要在对应的mapper上标注@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public@interfaceCacheRelations{//当from中mapper类对应的缓存更新时,缓存当前注解所注解的映射器需要更新Class>[]from()default{};//当前注解标记的mapper的缓存更新时,需要更新to中mapper类对应的缓存Class>[]to()default{};}自定义缓存RelativeCache实现MyBatisCache接口公共类RelativeCache实现缓存{privateMap