字典表和枚举的取舍

osc4067080 发布于 2021/12/01 17:58
阅读 2K+
收藏 5

数据库设置了字典表。里面有字典 sex:1男 2女

那么在假如说,在新增用户的时候,我需要做user.setSex(1)吗?

这不是魔法值吗?

我更期望以前的设置枚举,enum SEX{ MAN, WOMAN}

那么我新增的时候是user.setSex(SEX.MANxxx).

字典表该如何用好呢?

加载中
1
喜之郎
喜之郎

以前我也追求完美,想把所有的字典都定义对应枚举,多年的实践发现这样反而把事情搞复杂了。我感觉要做的是在数据库注释中和user.setSex(1)这句代码后面写好注释 //1代表什么,2代表什么即可。建议数据库中用“m”(male)代表男,“f”代表女,这样数据库中的数据更具有可读性。如果说要用枚举的话,mysql本身就支持枚举类型,但我也没见几个人用的。

osc4067080
osc4067080
回复 @魔力猫 : 下面有其他人回复说生成
osc4067080
osc4067080
这样祖传几代就完了。
魔力猫
魔力猫
MySQL的枚举,有人举了8宗罪。总之设计看起来还好,但是现实糟糕。还不如按范式原则搞字典表。纯数据库领域,还是按规范来吧。枚举还是放在代码里面考虑比较好。唯一要考虑的就是,代码里面的枚举和数据库里面的值的对应转换问题。
0
sprouting
sprouting

首先,存字典的作用是啥,一般用于哪里?当然是用于前端了,前端取值就从你的字典中来,前端将对应的数据传给你,你怎么需要再去字典中获取一次呢?

只有这个时候用到导入用户的需求,你需要做一次转换,这个时候,如果已经确定是保存在字典中了,就应该从字典获取,然后判断设置参数,全程根本不需要用到自定义的枚举。

osc4067080
osc4067080
说的好。这是一种思想,字典是给前端用的,是无逻辑意义的。
0
ArchitectureMaster
ArchitectureMaster

字典表和枚举并不冲突,并不是非此即彼,而是可以两者共存,这里的共存的方式并非是让你写两份。而是通常一份,另一份自动生成。先有数据sql创建字典表,再反射生成对应的enum。或生有enum再反向生成对应的字典表及数据。

1.两者共存的原因数据表里会有状态字段,而这个字段的值一般都是一个枚举值。而通常这个枚举值又需要与业务层代码操作。那很多初学者会要不写死,或硬性连接。

比方说员工表里员工状态:有在职、离职等。数据库里状态字段一般为0、1、2这样的值。而这样在编码时初学者为图方便会写上 "1"==status这样的东西而失去意义。再高级一点也只会再定义一个对应的enum枚举叫员工状态enum Status{former=0,current=1} Status.former == stratus。但这样做就会有一个问题,如果有一边的内容改了数据和代码逻辑对不上号。所以有必要共存。

2.本人的作法是使用code first方式,首先根据业务需求生成所有枚举字段及对应的值。然后再代码反射动态生成数据库对应的字典,数据字典的作用是方便查询和关联。而平常使用时,如果需要向前台输出时直接使用反射将Enum反射成列表,至于一楼所说的可读性的问题,这不有@元数据或attribute特性吗?利用反射加特性的特点,将枚举反射成map没什么问题吧。

3.请大胆使用底层技术,不要被什么所谓反射性能差所迷惑,assembly反射出来的对象性能再差,也不会比你从数据库里select出来然后再用for循环组成一个map输出到前台要差。而且spring这样的框架也是利用了attribute这样的特性才现实了aop这样的法力操作,你相信自己也是可以的。没有什么技术是高山仰之的,都是人写的,别人可以用你只要愿也可以,没什么天生就能用得好,你不用怎么可能用得好呢?

回答题主的问题,解决这个问题很简单分三步:

1.定义一个enum sex不同的是加上@元数据 Annotation,自定义一个Annotation类,比方说就叫Described("男")male=0。最后枚举名称上也加上自定的特性Described("性别“).

2.代码调用时正常调用。同时写入数据库字典表时动态创建两张表,字典分类表和字典表。反射这个枚举,枚举名称及自定义的描述写入字典分类表,再生成主键GUID作为外键和相对应的两个枚举值、及每个枚举的值、名称、描述及外键的分类表编号写入到字典表即可。

3.sql查询时只需要使用枚举强转成int型,再与数据库里的枚举值查询即可。

4.如果是查询枚举列表则使用反射生成字典表类似的生成map返回即可。比直接数据库查询速度要快。而且由于你加上了described所以前端显示时有中文友好的显示,返回保存则使用int枚举值.

5.结合起来使用是最方便实用的!

zhaojunli
zhaojunli
大佬有没有现成的例子呢
osc4067080
osc4067080
回复 @喜之郎 : 说的好,有时候字典可能需要单独管理,在线自由添加。而不需要重新部署。
osc4067080
osc4067080
不错不错。我也曾想过在系统启动的时候刷新字典表。只是污染担心历史数据
喜之郎
喜之郎
我感觉还有一点要考虑到。那就是不是所有的字典数据都适合定义为枚举。像性别“男”,“女”,选项相对固定就适合,另外有一些跟用户业务相关的字典,例如“科技领域”,选项可能有成百上千,用户还需要动态添加一个分类。不可能用户在字典管理中添加了分类我们还要重新生成代码对应的枚举吧。
0
s
shuaizai88
首先 我干了十年枚举很少用,可以采用常量的方式 SEX_BOY=1 来解决魔鬼数字问题,第二就是 像 这种两个选项的可以采用 isBoy 来起字段名,然后 常量 保持yes 或者no 就ok 了 setIsBoy(Constant.YES) 这样又省代码 可读性又高。
0
侯坤林
侯坤林
我个人的操作是,后端需要参与固定类型业务逻辑判断的就用枚举,后端不参与业务逻辑的就用字典数据。 假如一个状态字段,如果后端有需求必须为某种状态的数据才能进行修改、提交、审核或者其他业务操作,这时候我会用枚举,因为它的某种状态我需要参与业务操作写死在代码里了
0
码农小胖哥
码农小胖哥

enum SEX{ MAN("1","男"), WOMAN("0","女")}    解决这个问题    统一范式  然后做范式处理   无业务入侵  无感知  ,另外用SEX不太好建议用gender 

0
isureker
isureker

想不明白类似性别这种长时间固定的为啥要用字典表存储

TGVvbmFyZA
TGVvbmFyZA
也可以是流动的 (doge
0
yl-yue
yl-yue
https://ylyue.cn/#/规约/数据库设计与交付规约?id=枚举规约 这里能给你答案
0
昵称未定义
昵称未定义

枚举可以消除魔法数字,一般是有限可枚举的内容才会使用枚举。

而字典表,更多是那种虽然可以枚举出来,但是数量很多,并且可以随时可以配置新增或删除的内容。

枚举增加或减少得改代码再发布才行,不能像字典表那样灵活配置,实际使用时最好是根据实际场景分开,不然你要同时维护两份数据,那是很坑的。

而同一个配置既有字典又有枚举,真正的原因是后端为了偷懒搞出来的,要返回给前端时,只要统一查下数据库就行,最多就加个缓存,简单轻松,如果字典和枚举分开,那接口写起来就麻烦些。

0
华夏第一帅神
华夏第一帅神

像 true/false 这种,我觉得定义常量即可, 对于状态(0,1,2,3 ...)/ (READY,PAYING ... FINISH)这种比较多的,建议使用枚举。

OSCHINA
登录后可查看更多优质内容
返回顶部
顶部