mysql:为什么我需要attributeconverter over enum来Map一个拥有enum数据类型为enum的db列和一个jpa实体?

lkaoscv7  于 2021-06-24  发布在  Mysql
关注(0)|答案(1)|浏览(504)

我正在吃晚饭 user 数据库表为:

CREATE TABLE IF NOT EXISTS `user` (
  `user_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `first_ name` VARCHAR(45) NOT NULL,
  `active_status` ENUM('ACTIVE', 'PENDING', 'DEACTIVATED', 'BLOCKED', 'SPAM', 'DELETED') NOT NULL ,
  UNIQUE INDEX `unique_id_UNIQUE` (`unique_id` ASC),
  UNIQUE INDEX `email_UNIQUE` (`email` ASC),
  PRIMARY KEY (`user_id`))
ENGINE = InnoDB;

我将其Map到相应的jpa实体类,如下所示:

@Entity
public class User implements OfloyEntity {

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "user_id", unique = true, nullable = false)
private int userId;

//other fields

@Enumerated(EnumType.STRING)
@Column(name = "active_status", nullable = false, length = 11)
private UserStatus activeStatus;

如你所见,我已经绘制了 activeStatusenum UserStatus 限制持久层本身的实体。

public enum UserStatus {

    ACTIVE,
    PENDING,
    DEACTIVATED,
    BLOCKED,
    DELETED,
    SPAM
}

我想知道使用这种方法在持久层实现db enum有什么缺点吗?我抛出了多篇文章,其中建议使用attributeconverter,但由于我的枚举中的值非常有限,修改的机会较少,我无法将所有这些文章与我的要求联系起来。
我的设计中是否有遗漏或改进之处?
我扔的文章:
弗拉德米哈尔恰
索班和其他一些问题。
更新:在阅读了jens的答案之后,我决定实施 AttributeConverter (供用户参考) gender ). 这让我有点困惑:
为什么我决定使用enum作为mysql列类型:因为它限制了值并且需要更少的空间。因为mysql在场景后面存储枚举的序数值,当被要求提供值时,它表示枚举的字符串值,所以它节省了空间。
我对性别的理解:

public enum UserGender {

    MALE('M'),
    FEMALE('F'),
    OTHER('O');

    private Character shortName;

    private UserGender(Character shortName) {
        this.shortName = shortName;
    }

    public Character getShortName() {
        return shortName;
    }

    public static UserGender fromShortName(Character shortName) {
        switch (shortName) {
        case 'M': return UserGender.MALE;

        case 'F' : return UserGender.FEMALE;

        case 'O' : return UserGender.OTHER;

        default:
            throw new UserGenderNotSupportedException("user gender with shortName : " + shortName + " not supported");
        }

    }

}

转换器等级:

@Converter(autoApply = true)
public class UserGenderConverter implements AttributeConverter<UserGender, Character> {

    @Override
    public Character convertToDatabaseColumn(UserGender userGender) {
        return userGender.getShortName();
    }

    @Override
    public UserGender convertToEntityAttribute(Character dbGender) {
        return UserGender.fromShortName(dbGender);
    }

}

现在,主要的疑问是:
1根据博客,使用 MYSQL enum 在db中是邪恶的,因为如果有一天我需要向enum列添加额外的值,这将需要一个表alter,但是使用 AttributeConverter ? 因为我们也使用 java enum 如果有一天需要新的性别,哪一个需要改变?
2如果我使用 AttributeConverter ,我将不得不记录java enum ( UserGender 这里)解释某处,以便dba能够理解f,m,o代表什么。我就在这里吗?

t30tvxxf

t30tvxxf1#

这些文章为您提供了丰富的潜在缺点选择:
使用 @Enumerated(EnumType.STRING) 具有以下特性:
与其他选项相比,它占用了大量空间。请注意,这意味着需要通过导线加载和传输更多数据这也会影响性能。我们不知道这是否是一个问题,你也不会知道,直到你做了一些性能测试。
将枚举值的名称硬绑定到列值。这可能是有风险的,因为开发人员习惯于快速重命名东西,而且您需要使用实际遗留数据进行测试才能捕捉到这一点。
如果您不处理大量的数据,而更新所有行的列是一个实际的问题,我就不会担心了。引入一个 AttributeConverter 当简单的解决方案变成问题时更新数据。

关于更新问题的更新:

我不相信任何事情都是“邪恶”的说法,因为它可能需要 ALTER TABLE 声明。根据这个论点,我们应该完全废除关系数据库,因为使用它们需要ddl,而应用程序的演化将需要更多的ddl。当然,ddl语句的必要性使得部署更加复杂。但你无论如何都要有能力处理这件事。
但事实上 AttributeConverter 在这种情况下,您不需要任何ddl,因为您只需将另一个值放在同一列中,除了该值的最大长度之外,该列没有任何特殊约束。这假设您对列没有限制合法值的check约束。
你必须记录 Enum 以及数据库中存储的值?取决于你的团队。dba是否关心数据的含义?dba是否有访问权限和理解java代码的技能?如果dba需要或者想要知道,但是不能或者不想从源代码中获取信息,那么您必须对其进行文档化。是的。

相关问题