因数据库中存的都是数字(数据字典),但是又没有数据字典表,只有后端知道是什么意思,查询返回给前端时,需要if-else进行转换成具体的值,很麻烦,现增加数据字典表,通过redis获取,转换成具体的值
1.建表
CREATE TABLE `data_dictionary` (
`id` bigint(20) NOT NULL COMMENT '主键id',
`module` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '归属模块',
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '字典名',
`code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '字典编码',
`value` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '字典取值',
`order` int(3) NOT NULL DEFAULT -1 COMMENT '排序',
`state` tinyint(1) NOT NULL DEFAULT -1 COMMENT '启用状态 0:停用 1:启用',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
)ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '数据字典表';
2.mybatisplus生成controller,service,mapper,do等,下面是用到的DO,VO
@Data
@TableName("data_dictionary")
@ApiModel(value="DataDictionaryDO对象", description="数据字典表")
public class DataDictionaryDO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键id")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@ApiModelProperty(value = "归属模块")
private String module;
@ApiModelProperty(value = "字典名")
private String name;
@ApiModelProperty(value = "字典编码")
private String code;
@ApiModelProperty(value = "字典取值")
private String value;
@ApiModelProperty(value = "排序")
private Integer sort;
@ApiModelProperty(value = "启用状态 0:停用 1:启用")
private Integer state;
@ApiModelProperty(value = "创建时间")
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
}
@Data
@ApiModel(value = "DateDictionaryVo对象", description = "数据字典Vo")
@ToString
public class DataDictionaryVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "字典编码")
private String code;
@ApiModelProperty(value = "字典取值")
private String value;
@ApiModelProperty(value = "redis key")
private String key;
}
3.数据字典常量
/**
* @description:数据字典常量
*/
public class DataDictionaryConstant {
/**
* redis中数据字典key
*/
public static final String DATA_DICTIONARY_KEY = "dataDictionary";
/**
* 合同-执行状态
*/
public static final String CONTRACT_STATUS = "contract:status";
}
4.redis配置
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
// 创建RedisTemplate对象
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 设置连接工厂
template.setConnectionFactory(connectionFactory);
// 创建JSON序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 设置Key的序列化
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
// 设置Value的序列化
template.setValueSerializer(jsonRedisSerializer);
template.setHashValueSerializer(jsonRedisSerializer);
// 返回
return template;
}
}
5.实现springboot启动查询数据字典表,将数据缓存到redis中,使用@PostConstruct注解
/**
* @description:项目启动初始化数据字典到redis
*/
@Slf4j
@Component
public class InitConfig {
@Autowired
private DataDictionaryMapper dataDictionaryMapper;
@Autowired
RedisTemplate<String, Object> redisTemplate;
@PostConstruct
public void initDataDictionary() {
log.info("初始数据字典信息-开始");
if (Boolean.TRUE.equals(redisTemplate.hasKey(DATA_DICTIONARY_KEY))) {
redisTemplate.delete(DATA_DICTIONARY_KEY);
}
List<DataDictionaryDO> dictionaryDOList = dataDictionaryMapper.selectList(null);
Map<String, List<DataDictionaryVo>> dataMap = dictionaryDOList.stream().map(obj -> {
DataDictionaryVo dataDictionaryVo = new DataDictionaryVo();
dataDictionaryVo.setCode(obj.getCode());
dataDictionaryVo.setValue(obj.getValue());
dataDictionaryVo.setKey(obj.getModule() + ":" + obj.getName());
return dataDictionaryVo;
}).collect(Collectors.groupingBy(DataDictionaryVo::getKey));
redisTemplate.opsForHash().putAll(DATA_DICTIONARY_KEY, dataMap);
log.info("初始数据字典信息-结束");
}
}
7.redis中查看,可以看到redis在序列化对象时,把类信息(@class)也序列化进来了,这样存的作用是反序列化时知道反序列化成什么对象,但是浪费了内存空间;不想存类信息的话,需要手动序列化成字符串再存进来,获取时再手动反序列成对象,看你怎么选择了
8.将获取封装成一个工具方法,方便调用
@Service
public class RedisService {
@Autowired
private RedisTemplate redisTemplate;
/**
* 缓存中查数据字典
* @param key redis key
* @param code 字典编码
* @return
*/
public String getDataDictionary(String key, String code) {
String value = null;
if (Boolean.TRUE.equals(redisTemplate.hasKey(DATA_DICTIONARY_KEY))) {
List<DataDictionaryVo> dataDictionary = (List<DataDictionaryVo>) redisTemplate
.opsForHash().get(DATA_DICTIONARY_KEY, key);
if (dataDictionary.size() > 0) {
value = dataDictionary.stream().filter(obj -> code.equals(obj.getCode()))
.findFirst().get().getValue();
}
}
return value != null ? value : "";
}
}
为什么要这么写
Boolean.TRUE.equals(redisTemplate.hasKey(key))
而不是redisTemplate.hasKey(DATA_DICTIONARY_KEY)
这是因为idea提示可能会出现空指针,然后查资料修改成上面的写法
https://blog.csdn.net/qq_40822742/article/details/112291105
9.使用
//使用
String value = redisService.getDataDictionary(CONTRACT_STATUS, "0");
System.out.println(value);