第一步固然是建立一个springBoot项目,并导入依赖嘛。这就很少说了。
这儿咱们就不用jedis了,spring对redis也有支持,咱们就用spring-boot-starter-data-redis来整合redis。java
<!--https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.3.5.RELEASE</version> </dependency>
spring: #redis 的配置 redis: host: localhost port: 6379 database: 0 # 数据源,我用了druid datasource: type: com.alibaba.druid.pool.DruidDataSource password: 12345678 username: root url: jdbc:mysql://localhost:3306/redis?characterEncoding=UTF-8 druid: stat-view-servlet: url-pattern: /druid/* login-password: 123456 login-username: admin #mybatis 的配置 mybatis: mapper-locations: classpath:/mapper/*.xml # 配置日志打印 logging: level: com.tao.redis_demo_springboot.dao: debug
## 环境
咱们来搭建基本的一个增删该查
咱们新建一个测试类,来测试一下
那咱们该如何让redis进行缓存呢?
在mybatis中,咱们能够经过cache标签来开启二级缓存,这个默认的缓存是org.apache.ibatis.cache.impl.PerpetualCache
来实现的。
在cache标签中,type能够指定缓存类。那咱们能够自定义一个缓存类,用springboot提供的redistemplate 来对redis进行操做。也就是说,咱们经过这个自定义的缓存类来操做redis,咱们也就成功地用redis来作缓存了。mysql
那咱们如何来定义一个缓存类呢?
咱们能够看看mybatis他是如何实现的,咱们能够照猫画虎,去看看PerpetualCache
的源码。redis
public class PerpetualCache implements Cache { private final String id; private final Map<Object, Object> cache = new HashMap<>(); public PerpetualCache(String id) { this.id = id; } @Override public String getId() { return id; } @Override public int getSize() { return cache.size(); } @Override public void putObject(Object key, Object value) { cache.put(key, value); } @Override public Object getObject(Object key) { return cache.get(key); } @Override public Object removeObject(Object key) { return cache.remove(key); } @Override public void clear() { cache.clear(); } @Override public boolean equals(Object o) { if (getId() == null) { throw new CacheException("Cache instances require an ID."); } if (this == o) { return true; } if (!(o instanceof Cache)) { return false; } Cache otherCache = (Cache) o; return getId().equals(otherCache.getId()); } @Override public int hashCode() { if (getId() == null) { throw new CacheException("Cache instances require an ID."); } return getId().hashCode(); } }
一看源码就很清晰了,他是用一个map来管理缓存。那能够把缓存在redis中也写成一个map的格式。算法
那么咱们能够来编写一个本身定义的缓存类,来实现Cache接口。
在这以前,咱们须要考虑如何在这个缓存类中拿到RedisTemplate呢?咱们能够写一个工具类,继承于ApplicationContextAware类,这样咱们能够经过这个类来拿到spring中的redisTemplate。spring
@Component public class ApplicationContextUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext Context) throws BeansException { applicationContext = Context; } public Object getBean(String beanName){ Object bean = applicationContext.getBean(beanName); return bean; } }
接下来咱们在自定义的缓存类中就能够拿到redisTemplate了并实现Cache中的方法。sql
public class RedisCache implements Cache { private final String id ; public RedisCache(String id) { this.id = id; } @Override public String getId() { return this.id; } @Override public void putObject(Object o, Object o1) { getRedisTemplate().opsForHash().put(id.toString(),o.toString(),o1); } @Override public Object getObject(Object o) { return getRedisTemplate().opsForHash().get(id.toString(), o.toString()); } @Override public Object removeObject(Object o) { return null; } @Override public void clear() { getRedisTemplate().delete(id.toString()); } @Override public int getSize() { int size = Math.toIntExact(getRedisTemplate().opsForHash().size(id.toString())); return size; } private RedisTemplate getRedisTemplate(){ ApplicationContextUtil applicationContextUtil = new ApplicationContextUtil(); RedisTemplate redisTemplate = (RedisTemplate) applicationContextUtil.getBean("redisTemplate"); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); return redisTemplate; } }
而后咱们在mybatis中的mapper 的xml中添加上cache标签,并把type设置为咱们自定义的缓存类。这时候咱们的redis中就会存在咱们查询过的结果了。apache
redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer());
由于咱们在redis中存储的数据是String类型的,因此咱们须要将其序列化而后再存储到redis中。缓存
优化:咱们能够将那么一大串的key缩短,例如使用md5算法,将key统一地变为32位的16进制数字。springboot
mybatis中的二级缓存会在进行写操做的时候,会将该mapper中的缓存清空。可是,,咱们考虑一下,若是是多表更新呢,在A mapper中的更新语句中更新了B的某个记录的值,那么,B的缓存中没有作对应的修改,这样就会致使脏读,督导一个错误的数据。为了解决这个问题,能够将cache标签中的改成cache-ref,将这个缓存指向关联表的mapper。
例如:在A的mapper <cache type="com.tao.redis_demo_springboot.cache.RedisCache"/>
而B的mapper 为<cache-ref namespace="com.tao.redis_demo_springboot.dao.UserMapper"/>
mybatis