sdbybyd
V2EX  ›  Java

Java enum 数据库存储问题(大家都是存字符串还是数值)

  •  1
     
  •   sdbybyd · Sep 25, 2020 · 6493 views
    This topic created in 2070 days ago, the information mentioned may be changed or developed.

    想问下大家怎么存储 enum 的,是字符串存储还是数值存储? 比如:

    Gender { MALE, FEMALE }

    41 replies    2020-09-30 17:30:21 +08:00
    lower
        1
    lower  
       Sep 25, 2020
    byte
    lower
        2
    lower  
       Sep 25, 2020
    @lower 说错了,bit
    sdbybyd
        4
    sdbybyd  
    OP
       Sep 25, 2020
    @lower 你 @ 了自己,bit 指的是数值瞄?
    GM
        5
    GM  
       Sep 25, 2020
    以下为我经常使用的做法,定义一个 enum,enum 里定义好 Json 、Jpa 等转换规则。

    仅供参考:

    ```
    @Getter
    @AllArgsConstructor
    public enum State {
    UNKNOWN("未知"),
    ACTIVE("正常"),
    INACTIVE("封禁"),
    ;

    private final String desc;

    @JsonCreator
    public static State fromStr(String strValue) {
    return Arrays.stream(State.values()).filter(value -> value.value().equals(strValue)).findFirst().orElse(UNKNOWN);
    }

    @JsonValue
    public String value() {
    return this.name();
    }

    @Converter(autoApply = true)
    public static class DatabaseColumnConverter implements AttributeConverter<State, String> {
    public String convertToDatabaseColumn(State state) {
    return state != null ? state.name() : UNKNOWN.name();
    }

    public State convertToEntityAttribute(String name) {
    return fromStr(name);
    }
    }
    }

    ```
    xiangyuecn
        6
    xiangyuecn  
       Sep 25, 2020   ❤️ 1
    enum 能做的 class 都能做。

    enum 不能做的 class 都能做。

    enum 各种蹩脚规范代码编写约束,本质上还是一个 class,但开头不能放别的东西,气不气人?

    有什么理由用 enum ?没有!
    chana71
        7
    chana71  
       Sep 25, 2020
    @huijiewei 你这个是撸了个枚举类吗
    GM
        8
    GM  
       Sep 25, 2020
    @xiangyuecn enum 能 switch case,class 能吗?
    GM
        9
    GM  
       Sep 25, 2020
    @xiangyuecn
    enum 可以直接 if(user.state == State.INACTIVE) { ... },class 能吗?
    huijiewei
        10
    huijiewei  
       Sep 25, 2020
    @GM 我贴的代码可以啊

    user.state == UserState.INACTIVE.getValue()

    即可
    yiyi11
        11
    yiyi11  
       Sep 25, 2020 via Android
    啊?不是都存码表的码吗?数据库有码表,1-xxx,2-yyy,其他表存的是码“1”或“2”。枚举定义成 xxx(“1”,“xxx”)。不管哪里的数据都是以码为准,码对应的值是描述解释(或做显示用),枚举仅仅是为了消除代码中的魔法值,跟码表一一对应的。
    GM
        12
    GM  
       Sep 25, 2020
    @huijiewei
    enum 存字符串的好处主要是一目了然,不用看着表里的 1 、2 、3 、4 去猜,比较方便。不然就得去代码里找对应文档或注释(碰到那些缺乏注释的项目,会很恶心)。

    PS:多一个 .getValue() 感觉还是很不爽的,不如直接 user.state == UserState.INACTIVE
    baobao1270
        13
    baobao1270  
       Sep 25, 2020
    不是 Java,是 .NET ,存 Enum 。数据库里写注释,再说,有 EFCore 基本很少要动数据库
    GM
        14
    GM  
       Sep 25, 2020
    @huijiewei 去看了一下你的代码,你这做法不是不行,但是定义、使用太麻烦了,不如 enum 好用。

    我个人是很喜欢 java 的 enum 设计的,用对路了会感觉很好用。事实上,我写 C#项目的时候,还专门弄了一个 Enum 类来模拟 java 的 enum 。
    wdmx007
        15
    wdmx007  
       Sep 25, 2020 via Android
    不推荐存数字,也就是 ordinal 。因为这是和枚举各项顺序有关的,有脑抽的调整了顺序就炸了
    lululau
        16
    lululau  
       Sep 25, 2020 via iPhone
    存数值也可以不存 ordinal value,可以自定义使用数值型属性的值的,但我认为应该存字符串,就一个原因,只看 db 存的值我就知道当前这条记录是什么状态、类型了
    MarioLuo
        17
    MarioLuo  
       Sep 25, 2020 via Android
    直接用字符串,许多框架库(spring, mybatis,...)对枚举默认值处理方式就是字符串
    EminemW
        18
    EminemW  
       Sep 25, 2020
    我的 enum 是用来看的。。不存数据库,因为我不知道怎么比较合理利用
    zsdroid
        19
    zsdroid  
       Sep 25, 2020
    @huijiewei 1 为什么不推荐用 ENUM ? 2.你的比 java 自带的好在哪?
    sdbybyd
        20
    sdbybyd  
    OP
       Sep 26, 2020
    @GM 这也是我现在在用的方法,就是列举一些值,写个 mybatis 的 converter 转换存储,但是我看了 fb 还有 阿里的很多接口,对外暴露用的字符串,这样 java 的 enum 就简单了,直接命名就行,mybatis 有默认 converter 插入,可能 fb 阿里都有自动化工具转值存储 db
    sdbybyd
        21
    sdbybyd  
    OP
       Sep 26, 2020
    @huijiewei 你这个做法应该不行,还不如手撸 converter
    sdbybyd
        22
    sdbybyd  
    OP
       Sep 26, 2020
    @xiangyuecn enum 的好处很多,比如类型检查(不是 Integer 数值类型检查),如果你可以直接这么写

    ```java
    public enum Gender {
    MALE,
    FEMALE;
    }
    ```

    而且有自动化工具帮你存储数据库时转换为数值存储,如 1,2,提取时自动转换,这种状态维护起来就简单多了

    我想要的就是这种自动化工具(不用硬编码数值,看了一些 api,fb 和阿里就有这么搞)。
    sdbybyd
        23
    sdbybyd  
    OP
       Sep 26, 2020
    @yiyi11 你说的数据库码表指的是?特定数据库类型?还是在 java 上编码的数值映射
    sdbybyd
        24
    sdbybyd  
    OP
       Sep 26, 2020
    @MarioLuo 直接用字符串的话,作为索引的时候是不是太浪费了,有没优化方法
    dswyzx
        25
    dswyzx  
       Sep 26, 2020 via iPhone
    c#里,enum 是值类型,class 可是引用类型。根本性不同。enum 映射 db 当然是数值类型了。二楼说 bit 的,刚好性别男女是够用了,以后扩展人妖或者啥啥的时候你怎么存
    MarioLuo
        26
    MarioLuo  
       Sep 26, 2020 via Android
    @sdbybyd 数据量不高的情况下索性性能差异不大, 而且大多数情况下枚举字段并不适合作为索引列
    MarioLuo
        27
    MarioLuo  
       Sep 26, 2020 via Android
    @sdbybyd 枚举增加数值属性, 实现 IntCode 接口,然后为相关的库针对这个接口通用的转换器(mybatis, jpa, spring mvc,...)

    enum Gender implement IntCode{
    MALE(1),
    FEMALE(2);
    private Integer code;
    public Integer getCode(){ return code; }
    }

    interface IntCode{
    Integer getCode()
    }
    binux
        28
    binux  
       Sep 26, 2020 via Android
    数据库也用枚举类型不就完了
    huijiewei
        29
    huijiewei  
       Sep 26, 2020
    @zsdroid 不用 ENUM 是因为如果数据库里面有 ENUM 不存在的值。API 输出会很麻烦
    huijiewei
        30
    huijiewei  
       Sep 26, 2020
    @binux 因为大部分人用 mysql,mysql ENUM 类型坑比较多,现在都不推荐使用 ENUM
    ez728s
        32
    ez728s  
       Sep 26, 2020 via Android
    数据库里面应该存储有明确意义的字符串值而不是不知所谓的 1234 数值
    xiangyuecn
        33
    xiangyuecn  
       Sep 26, 2020
    @sdbybyd #22 解决硬编码数值(应该叫魔术数值)问题,应当首选常量,而不是 enum,比如 Android 里面的 startActivityForResult 中的 requestCode 这个反人类数值参数,用 enum 当然可以,但不会去用的,基本定义成常量的
    zeroday
        34
    zeroday  
       Sep 26, 2020
    直接用 mysql 里的 ENUM 类型. 因为是非常快和紧凑的。在实际上,其保存的是 TINYINT,但其外表上显示为字符串。
    如果有一个字段,比如“性别”,“国家”,“民族”,“状态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 。
    yiyi11
        35
    yiyi11  
       Sep 26, 2020 via Android
    @sdbybyd 数值映射
    tailf
        36
    tailf  
       Sep 26, 2020
    数据库不要用 enum,用 tinyint
    skypyb
        37
    skypyb  
       Sep 26, 2020
    用 postgres 就没这破事了
    notejava
        38
    notejava  
       Sep 26, 2020
    字符串,可读性好
    tairan2006
        39
    tairan2006  
       Sep 26, 2020
    tinyint/smallint
    sdbybyd
        40
    sdbybyd  
    OP
       Sep 30, 2020
    @MarioLuo 我们目前就是这么做的,但是还是需要定义数值,数值定义不好规范,想要数据库插入就是字符串(实际存储用的数值)这部分对开发者隐藏的同时规避 数据库 enum 类型的缺陷
    MarioLuo
        41
    MarioLuo  
       Sep 30, 2020 via Android
    @sdbybyd 那问题就是数字从哪儿来,依赖枚举 ordernal 是不应该的
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5361 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 83ms · UTC 07:02 · PVG 15:02 · LAX 00:02 · JFK 03:02
    ♥ Do have faith in what you're doing.