前言:
由于查询效率过慢,我们考虑将平常使用被查询且不大改动的表或字段放入缓存中,这样就不需要重复和数据库交互,提高性能。
前面使用通用mapper的文章中tk.mybatis依赖包导的版本是1.1.3的改为2.0.3.
否则在使用selectAll时会报错,这里具体原因还没找到!
Redis使用
本地下载redis,这里可以在官网下载一下,下载之后打开下载文件
启动redis-server.exe后(要以管理员权限打开)
打开redis-cli.exe界面,可以查看缓存键值对信息
下载可视化插件(Redis Desktop Manager)可以更直观的看见键值对信息
下载完成是这样的界面:
配置连接信息:用户名/ip/端口号/密码
redis查默认密码:config get requirepass
修改密码:
config set requirepass cmf
auth cmf
requirepass / 127.0.0.1 / 6379 / cmf :登陆成功后,可以看见后面使用java代码设置的键值对信息:
1、导入依赖
<!-- 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.4.3</version>
</dependency>
2、在service里面注入RedisTemplate类,该类提供了对redis各种操作
我在写缓存中用的以下几个方法
-- 设置缓存键值
redisTemplate.opsForHash().put(hash,hashkey, hashvalue);
-- 根据hash删除缓存
redisTemplate.delete(hash);
-- 以集合的方式获取变量的值(在hash键值中以多个hashkey集合取出hashvalue集合)
redisTemplate.opsForHash().multiGet(hash, hashkeyList);
-- 获取变量中的键值对Map<hashkey, hashvalue>
redisTemplate.opsForHash().entries(hash);
缓存类:
package com.cmf.demo.service.cache;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cmf.demo.mapper.TestMapper;
import com.cmf.demo.orm.UserEntity;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class TuserCache {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private TestMapper testMapper;
public void init(){
//写个初始化方法一开始在类加载的时候就把数据库的信息一次性放入redis缓存中
List<UserEntity> userEntities = testMapper.selectAll();
for(int i=0;i<userEntities.size();i++){
//这里没有用数据库,这块应该是查询数据库的信息,然后用put方法放进缓存
UserEntity entity = userEntities.get(i);
redisTemplate.opsForHash().put("userId","userId"+entity.getUserId(), JSONObject.toJSONString(entity));
redisTemplate.opsForHash().put("userStatus","userStatus"+entity.getUserStatus(),JSONObject.toJSONString(entity));
}
}
public List<UserEntity> getUserList(){
List<UserEntity> userEntityList = new ArrayList<>();
Map<String,String> userMap = redisTemplate.opsForHash().entries("userId");
for(Entry<String,String> entry : userMap.entrySet()){
Object entity = entry.getValue();
UserEntity userEntity = JSON.parseObject(entity.toString(),UserEntity.class);
userEntityList.add(userEntity);
}
return userEntityList;
}
public String getName(String userId){
Object user = redisTemplate.opsForHash().get("userId","userId"+userId);
UserEntity entity = JSON.parseObject(user.toString(),UserEntity.class);
return entity.getUserName();
}
public List<String> getNames(List<String> userIds){
List<String> userNameList = new ArrayList<>();
List<Object> users = redisTemplate.opsForHash().multiGet("userId",userIds);
for(Object user : users){
UserEntity entity = JSON.parseObject(user.toString(),UserEntity.class);
userNameList.add(entity.getUserName());
}
return userNameList;
}
}
service核心代码:
public UserEntity getUser(String id){
List<UserEntity> userEntities = tuserCache.getUserList();
log.debug("缓存获取所有用户信息:");
for(int i=0;i<userEntities.size();i++){
log.debug(userEntities.get(i).toString());
}
log.debug("缓存获取对应的用户名:");
String name =tuserCache.getName("20030001");
log.debug(name);
return new UserEntity();
}
3、编译通过但运行时报连接问题,yml需配置下面参数
spring:
redis:
#Redis服务器地址
host: 127.0.0.1
#Redis服务器端口
port: 6379
4、调用service方法方法缓存查询出来为空,其实是在bean创建时就应该执行缓存初始化方法的,不然的话缓存里面一直是空,查询出来自然没有值;
写个缓存管理类,执行init方法
- 首先如果想在项目初始化的时候就执行init方法,可以让缓存管理类实现InitializingBean接口,继而实现afterPropertiesSet的方法。凡是继承该接口的类,在初始化bean的时候都会执行该方法。
CacheManage
@Service
public class CacheManage implements InitializingBean {
@Autowired
private TuserCache tuserCache;
@Override
public void afterPropertiesSet() throws Exception {
tuserCache.init();
}
}
这样在项目启动加载bean的时候缓存初始化就成功了。后面调用user修改数据的时候就可以通过UserCache类之间在redis缓存中获取了。
5、补充,上文用到了JSONObject.toJSONString(Object o)及JSON.parseObject(String s,Object.class)方法,这里是把对象转为json字符串和把json字符串转为对象的方法,使用该方法前,必须引入下面依赖
<!-- 由alibaba开源的一套json处理器 序列化反序列号 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
6、缓存后续还需增加更新和删除的方法。因为用户信息也可能被修改,数据库中数据被修改后,缓存也应该有刷新功能,否则需要重启项目很不方便;