SpringBoot+Redis实现数据字典的方法
作者:溪源的奇思妙想 发布时间:2022-08-03 14:22:29
前言
我们在日常的开发过程中针对一些字段采用整型的方式去代替某些具体的含义,比如性别0代表男,1代表女。如果只是一些不会变更的转译我们可以采用常量或者枚举类的方式来实现,但是事实上我们也会遇到那种可能需要变更的,显然这种场景下使用枚举类这种方式是不合理的,那么如何动态地去进行转译呢?
正文
数据字典
数据字典(Data dictionary)是一种用户可以访问的记录数据库和应用程序元数据的目录。主动数据字典是指在对数据库或应用程序结构进行修改时,其内容可以由DBMS自动更新的数据字典。被动数据字典是指修改时必须手工更新其内容的数据字典。
我们通常会结合数据库来实现数据字典,但事实上数据字典经常会被使用到,如果频繁地去访问数据库,将会对数据库造成性能压力,事实上我们经常会采用Redis对数据字典进行缓存来提升系统性能。
使用Redis的优势:
1.绝大数的请求操作都是纯粹的内存操作。
2.采用了单线模式,避免了不必要的上下文切换和竞争条件这里的单线程指的是网络请求模块只使用了一个线程(所以不必考虑并发安全性),即一个请求处理所有网络请求,其他模块仍使用了多个线程。
3.采用了动态字符串(SDS),对于字符串会预留一定的空间,避免了字符串在做拼接和截取引起内存重新分配导致性能的损耗。
SpringBoot+Redis实现数据字典
依赖
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<optional>true</optional>
</dependency>
application.properties:配置类
#redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
字典表:SYS_DICT
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for SYS_DICT
-- ----------------------------
DROP TABLE IF EXISTS `SYS_DICT`;
CREATE TABLE `SYS_DICT` (
`code` varchar(36) NOT NULL COMMENT '主键',
`type_code` varchar(36) DEFAULT NULL COMMENT '类型code',
`name` varchar(50) DEFAULT NULL COMMENT '展示值',
`value` int(20) DEFAULT NULL COMMENT '使用值',
`fixed` int(2) DEFAULT NULL COMMENT 'default 0不固定,固定的话用1',
`creater` varchar(20) DEFAULT NULL COMMENT '新建人',
`create_time` datetime DEFAULT NULL COMMENT '新建时间',
`updater` varchar(20) DEFAULT NULL COMMENT '编辑人',
`update_time` datetime DEFAULT NULL COMMENT '编辑时间',
PRIMARY KEY (`code`),
KEY `sys_type` (`type_code`),
CONSTRAINT `sys_type` FOREIGN KEY (`type_code`) REFERENCES `SYS_DICT_TYPE` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of SYS_DICT
-- ----------------------------
INSERT INTO `SYS_DICT` VALUES ('182d4db6-aa50-11ea-aa1b-00163e08c9ed', '9ed92c7e-aa4f-11ea-aa1b-00163e08c9ed', '男', '0', '1', null, null, null, null);
INSERT INTO `SYS_DICT` VALUES ('222cf983-aa50-11ea-aa1b-00163e08c9ed', '9ed92c7e-aa4f-11ea-aa1b-00163e08c9ed', '女', '1', '1', null, null, null, null);
字典类型表SYS_DICT_TYPE
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for SYS_DICT_TYPE
-- ----------------------------
DROP TABLE IF EXISTS `SYS_DICT_TYPE`;
CREATE TABLE `SYS_DICT_TYPE` (
`code` varchar(36) NOT NULL,
`name` varchar(50) DEFAULT NULL COMMENT '用于展示',
`value` varchar(50) DEFAULT NULL COMMENT '用于前段(建立唯一索引)',
`creater` varchar(20) DEFAULT NULL COMMENT '新建人',
`create_time` datetime DEFAULT NULL COMMENT '新建时间',
`updater` varchar(20) DEFAULT NULL COMMENT '编辑人',
`updater_time` datetime DEFAULT NULL COMMENT '编辑时间',
PRIMARY KEY (`code`),
UNIQUE KEY `key_value` (`value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of SYS_DICT_TYPE
-- ----------------------------
INSERT INTO `SYS_DICT_TYPE` VALUES ('9ed92c7e-aa4f-11ea-aa1b-00163e08c9ed', '性别', 'sex', null, null, null, null);
RedisConfigurtion:Redis配置类,解决Redis数据同步时字符串格式问题
@Configuration
public class RedisConfigurtion {
@Autowired
private RedisTemplate redisTemplate;
@Bean
public RedisTemplate<String, Object> stringSerializerRedisTemplate() {
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setValueSerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
redisTemplate.setHashValueSerializer(stringSerializer);
return redisTemplate;
}
}
SpringUtil:用于加载Spring容器
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringUtil.applicationContext == null){
SpringUtil.applicationContext = applicationContext;
}
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
}
RedisDistUtil:Spring容器不允许普通Pojo调用Service,所以采用以下方式手动通过Spring容器去加载Bean.
public class RedisDistUtil {
private static ApplicationContext context;
/**
* 转化码值
* @param distname
* @param value
* @return
* @throws Exception
*/
public static String transformStr(String distname, int value) {
ApplicationContext context = SpringUtil.getApplicationContext();
ISysDictService iSysDictService =context.getBean(ISysDictService.class);
return iSysDictService.transformStr(distname,value);
}
}
SysDictService
transformStr:从Redis中获取字典值。
refreshCache:用于将数据库数据字典表数据同步到Redis中。
@Transactional
@Service
@Slf4j
public class SysDictService implements ISysDictService {
@Autowired
SysDictPojoMapper sysDictPojoMapper;
@Autowired
RedisTemplate redisTemplate;
/**
* 转化码值
*
* @param distname
* @param value
* @return
* @throws Exception
*/
@Override
public String transformStr(String distname, int value) {
return redisTemplate.opsForValue().get(distname + "_" + value) != null ?
redisTemplate.opsForValue().get(distname + "_" + value).toString() : String.valueOf(value);
}
/**
* 刷新缓存
*/
@Override
public void refreshCache() {
log.info("start 刷新码表缓存");
List<SysDictPojo> sysDictPojoList = sysDictPojoMapper.getall();
long startTime = System.currentTimeMillis();
for (SysDictPojo sysDictPojo : sysDictPojoList) {
redisTemplate.opsForValue().set(sysDictPojo.getTypeCodeValue() + "_" + sysDictPojo.getValue(), sysDictPojo.getName());
}
long endTime = System.currentTimeMillis();
log.info("end 刷新码表缓存,总计:" + sysDictPojoList.size() + "条,用时:" + (endTime - startTime) + "毫秒");
}
}
SysDictPojo:数据字典的实体类
@Setter
@Getter
@ToString
public class SysDictPojo implements Serializable {
private static final long serialVersionUID = 7845051152365224116L;
private String code;
private String typeCode;
private String typeCodeValue;
private String name;
private Integer value;
private Integer fixed;
private String creater;
private Date createTime;
private String updater;
private Date updateTime;
}
getall:查询数据库的所有数据字典值
<select id="getall" resultType="com.luo.dao.entity.SysDictPojo">
select
t1.name,
t1.value,
t2.value typeCodeValue
from SYS_DICT t1
left join SYS_DICT_TYPE t2 on t2.code =t1.type_code
</select>
验证
UserPojoRes :在get方法里进行数据字典值的替换
@Setter
@Getter
@ToString
public class UserPojoRes implements Serializable {
private static final long serialVersionUID = -2145503717390503506L;
/**
* 主键
*/
private String id;
/**
* 姓名
*/
private String name;
/**
* 性别
*/
private int sex;
/**
* 性别展示
*/
private String sexStr;
/**
* 消息
*/
private String msg;
public String getSexStr() {
return RedisDistUtils.transformStr("sex",this.sex);
}
}
访问模拟接口,根据id查询用户信息:
来源:https://blog.csdn.net/weixin_40990818/article/details/106669371


猜你喜欢
- 本文实例讲述了C#使用GZipStream解压缩数据文件的方法。分享给大家供大家参考。具体分析如下:GZipStream用于从一个流读取数据
- 导航是指支持用户导航、进入和退出应用中不同内容片段的交互。Android Jetpack 的导航组件可帮助您实现导航,无论是简单的按钮点击,
- 一、定义登录控制器目录结构代码:1、创建TUser类package com.demo.pojo;import lombok.AllArgsC
- 说明Flutter原生是没有支持数据库操作的,它使用SQLlit插件来使应用具有使用数据库的能力。其实就是Flutter通过插件来与原生系统
- 本文讲解2点:1. fastjson生成和解析json数据(举例:4种常用类型:JavaBean,List<JavaBean>,
- 线程中run()和start()的区别:对于Thread对象来说,当你调用的是start(),线程会被放到等待队列,等待CPU调度,不一定马
- 摘要在生产环境下,我们需要关闭swagger配置,避免暴露接口的这种危险行为。方法禁用方法1:使用注解 @Value() 推荐使用packa
- 本文实例为大家分享了C# picturebox实现画图功能的具体代码,供大家参考,具体内容如下在Form上添加 一个pictureBox,一
- 数组:数组可以用来保存多个基本数据类型的数据,也可以用来保存多个对象。数组的长度是不可改变的,一旦初始化数组时就指定了数组的长度(无论是静态
- 为了解决在多个窗口之间的传值问题,我们可以通过设置静态类和静态变量的办法来实现窗口间值的传递窗体一代码//窗体1的代码using Syste
- 目录第一章 前言概述第01节 概述第02节 区别第二章 核心代码第01节 成员变量第02节 构造方法第三章 扩容操作第01节 扩容代码第一章
- 本文实例讲述了Android EditText限制输入字数的方法。分享给大家供大家参考,具体如下://新浪微博字数限制private sta
- 一、背景介绍最近在项目中遇到一个需求,实现一个后台拍照的功能。一开始在网上寻找解决方案,也尝试了很多种实现方式,都没有满意的方案。不过确定了
- 目录前言RenderObject 类继承层级解析RenderBox叶节点与父节点控件的测量与布局performResize 和 perfor
- Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RF
- 我们来讨论一个经常存在的账户转账的问题。账户A要转账给账户B。为了保证在转账的过程中A和B不被其他的线程意外的操作,我们需要给A和B加锁,然
- Failed to execute goal org.apache.maven.plugins:maven-resources-plugin
- 引出泛型我们通过如下的示例,引出为什么泛型的概念。public class Test {public static void main(St
- 我们知道在C语言编译时,有那么几个常用的优化编译选项,分别是-O0,-O1,-O2,-O3以及-Os。之前一直觉得既然是优化选
- 一、前言1.1 实现目标服务A调用服务B1和B2(B1和B2提供同种服务),当服务B1/B2在停止和重新发布阶段,或B1/B2有一个服务故障