一篇关于》数据字典在web系统中应用》实践

您所在的位置:网站首页 数据字典的含义和作用 一篇关于》数据字典在web系统中应用》实践

一篇关于》数据字典在web系统中应用》实践

2024-07-09 22:26| 来源: 网络整理| 查看: 265

之前很长一段时间,我都不知道数据字典如何在web系统中应用,在网上看完关于数据字典的应用方面的文章后,也是迷迷糊糊。博主写的长篇大论,貌似博主对数据字典很熟悉,但有时我看完之后,就产生了“写的什么玩意?”的想法。也难怪,数据字典这玩意说重要也重要,说不重要也不重,因为接触的少,所以才会感到陌生吧。在最近的项目中我们就实际用上了数据字典,用了之后才发现有了数据字典,整个系统的数据就会更加严谨了。

下面谈一下数据字典是如何在web系统中发挥作用的~~~

一、开发中产生的问题

1、我们在开发的过程中会经常遇到,一个事物有多个不同的状态或者多个不同的类型,反映到数据表中就是一个字段可能对应多个值的情况,如果这些值刚开始设计时就已经能确定,今后不会再改变,那用不用数据字典都可以;若这些值今后可能会发生改变,那就有使用数据字典的必要了,因为我们可以通过直接修改数字对应的数据字典的值,来改变它在系统中的意思。

2、再比如为了节省存储空间和开发方便,对于这种一个字段对应多个值的情况,我们一般用数字来代替,并且在项目中建立对应的常量类,来维持这种数字与真实含义的对应关系。那么问题来了,由于我们存储的是数字,如果查询完不作处理直接返回给前端,前端就要问后端这个数字代表什么意思,然后if-else-if、或switch-case做判断处理,对于"真正的前后端分离项目"——前后端开发人员地理位置上的分离(这种项目牛逼),沟通起来有点麻烦。有或者后端在给前端出接口文档时,将这个数字与实际含义的对应关系整理成单独的一页,放在接口文档中,直接让前端看也是可以的(注意啦,这一页的数字与实际含义的对应关系,就是一个简单的数据字典) 。ok,行,整理成文档给前端看是吧,没问题,这样前端就会将这个关系"硬编码"到代码中,如果以后要是想修改或者添加新的种类,怎么办——前端改代码,放到面向对象的设计模式中,这就是不符合最基本的——开闭原则!

二、怎么办?——重构

对于这种数字和实际含义对应关系的情况,我们如果在数据返回之前将数字对应的实际含义查询出来,前端页面只做显示作用,那就行了呗。到这里,后端开发人员需要有一个特殊的地方来保存这些数字和实际含义的对应关系,然后根据从数据表中查出来的数字,到这个特殊的地方,根据数字查询对应的值,返回给前端显示就完了。那么现在这个特殊的地方,我们就可以称之为——数据字典。

三、实践

经过上面的分析我们知道,数据字典需要两个操作——存储和快速查询

1、存储

存储就要考虑存储的数据格式了,经过上面分析我们知道数据字典就是典型的键值对格式。什么能存储键值对格式呢?properties文件、xml文件、json文件,别搞得花里胡哨,就用我们万能的mysql数据库就行。关于字段的设计也是仁者见仁智者见智,只要把握住两点即可:第一,k-v结构的数据格式;第二,方便查询。这里分享一下我们设计的表结构供大家参考。

数据字典表的设计

fieldName 为字段名,为了避免重复设计成表名_字段名的形式,可以理解成一组数据的组名。dicKey 为键值对中的key,对应其他数据表中存储的数值。dicValue 为键值对中的value,对应数值的实际含义。isField 为一个标识字段,用来表示这条数据是存储字段名的,没有k-v对。description 主要用于对字段名的描述,说明这一组数据是干嘛的。 2、快速查询

这里有个特点——快速。我们需要对前面查询出来的每一条数据的一个或多个字段,查询它对应的实际含义,这个查询数据是要比前面查询的数量要多的(查询的条数可按照公式:字段数 * 前面查询的记录条数 来计算)。为了实现快速查询,我们选择将数据同步到内存中来查询。

很少数据量的话,又为了项目结构简单,可以设计简单的缓存工具类:比如用一个静态的线程安全的HashMap来存储数据,并提供访问和操作HashMap的公共方法,像这样的~~~

private static Map map = new ConcurrentHashMap(300); public static Object getValue(String key){ return map.get(key); } public static void setValue(String key,Object value){ map.put(key,value); } //其他操作,增删改查等操作

由于我们项目中引入了redis,所以我们用redis做的缓存,redis的哈希这个数据类型就非常适合存储数据字典,由于数据字典的数据量不是很多,所以就用了一个哈希表来存储的:field的格式为表名_字段名_数值,value为数值的实际含义。

3、两个需要注意的点

1)mysql中的数值的数据类型最好用char(2),这样对应实体类的属性就是String,方便查询出实际含义后直接赋值给这个属性,就不用再增加新的属性来存储数据了。你要用map来接受数据,就当我没说。

2)最好是在项目启动的时候将mysql中的数据字典数据,同步到缓存中。

4、一些相关代码

dictionaryService(数据字典操作的一些接口)

@Override public void initDictionaryToRedis() { QueryWrapper wrapper = new QueryWrapper(); wrapper.eq("isField",DictionaryConstant.field.notField); List dictionaryList = dictionaryDao.selectList(wrapper); if (dictionaryList .isEmpty()) { logger.warn("数据字典为空,无法初始化数据到redis!"); }else { Map dicMap = new HashMap(dictionaryList.size()); for (Dictionary dic : dictionaryList) { dicMap.put(dic.getFieldName() + "_" + dic.getDicKey(),dic.getDicValue()); } RedisUtils.hmset(Constant.Redis.dictionaryHashMap,dicMap); logger.warn("初始化数据字典到redis成功!"); } } @Override public String getDicValueFromRedis(String fieldName, String dicKey) { String dicValue = RedisUtils.hget(Constant.Redis.dictionaryHashMap, fieldName + "_" + dicKey); return StringUtils.isEmpty(dicValue) ? dicKey : dicValue; } @Override public List getMoreDicValueFromRedis(String fieldName, String... dicKeys) { //构建哈希表的field for (int i = 0; i < dicKeys.length; i++) { dicKeys[i] = fieldName + "_" + dicKeys[i]; } List dicValueList = RedisUtils.hmget(Constant.Redis.dictionaryHashMap, dicKeys); //若divValue 的值为空,就返回dicKey的值 int i = 0; for (String dicValue : dicValueList) { if (dicValue == null){ dicValueList.set(i,dicKeys[i]); i++; } } return dicValueList; }

调用dictionaryService的方法,获取dicValue并赋值给实体类的属性

/*跟进记录的查看详情*/ @Override public ClueFollowReport selectFollowReportDetails(Long id) { ClueFollowReport followReport = clueFollowReportDao.selectFollowReportDetails(id); String followType = String.valueOf(followReport.getFollowType()); String dicValue = dicService.getDicValueFromRedis( DictionaryConstant.clueFollowReport_followType,followType) followReport.setFollowTypeStr(dicValue); return followReport; } /*操作日志*/ @Override public Page selectFollowRecord(Page page, Map map) { Page resultPage = clueFollowReportDao.selectFollowRecord(page, map); //根据数字值获取对应的实际含义 List records = resultPage.getRecords(); if (!records.isEmpty()) { String[] array = new String[records.size()]; for (int i = 0,size = records.size(); i < size ; i++) { array[i] = String.valueOf(records.get(i).getFollowType()); } List strList = dicService.getMoreDicValueFromRedis( DictionaryConstant.clueFollowReport_followType,array); int i = 0; for (ClueFollowReport followReport : records) { followReport.setFollowTypeStr(strList.get(i)); i++; } } return resultPage;

数据字典的操作,实现方式因人而异,主要是能理解为什么使用数据字典,使用完后会给项目带来什么好处,至于如何去做,就看你心情喽!

 

看完之后如果对你有帮助,点个赞再走呗!

 

 

 

 

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3