mysql - mysql:为什么我需要 AttributeConverter over enum 将具有枚举数据类型的 DB 列映射为枚举与 JPA 实体?
问题描述
我有一个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;
我将它映射到相应的 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;
如您所见,我已映射activeStatus
到 aenum UserStatus
以限制持久层本身的整体。
public enum UserStatus {
ACTIVE,
PENDING,
DEACTIVATED,
BLOCKED,
DELETED,
SPAM
}
我想知道使用这种方法在持久层中实现数据库枚举有什么缺点吗?我抛出了多篇推荐使用AttributeConverter的文章,但由于我的枚举中的值非常有限并且修改的机会较少,我无法将所有这些文章与我的要求联系起来。
有什么我遗漏的,或者我的设计可以做任何改进吗?
我扔的文章:
vladmihalcea
thorban和其他一些 stackoverflow 问题。
更新:阅读 Jens 的答案后,我决定实施AttributeConverter
(针对用户的gender
)。这让我有点困惑:
为什么我决定使用枚举作为 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 中使用是邪恶的,因为有一天如果我需要向枚举列添加额外的值并且需要一个表 ALTER,但使用的情况不一样AttributeConverter
吗?因为我们也使用 a java enum
,如果有一天需要新的性别,这需要改变吗?
2. 如果我使用AttributeConverter
,我必须在某处记录 java enum
(UserGender
此处)解释,以便 DBA 能够理解 F、M、O 代表什么。我在这里吗?
解决方案
这些文章为您提供了丰富的潜在缺点选择:
使用@Enumerated(EnumType.STRING)
有以下几点:
- 与其他选项相比,它使用了大量空间。请注意,这意味着需要通过网络加载和传输更多数据,这也会影响性能。我们不知道这是否对您来说是个问题,并且您也不会知道,直到您进行了一些性能测试。
- 将枚举值的名称与列值紧密联系起来。这可能是有风险的,因为开发人员习惯于快速重命名东西,并且您需要使用实际的遗留数据进行测试才能捕捉到这一点。
如果您不使用真正大量的数据,而更新所有行的列是一个实际问题,我不会出汗。AttributeConverter
当简单的解决方案实际上成为问题时,引入和更新数据很容易。
关于更新问题的更新:
我不接受任何东西都是“邪恶”的论点,因为它可能需要一个
ALTER TABLE
声明。根据这个论点,我们应该完全废除关系数据库,因为使用它们需要 DDL,而应用程序的发展将需要更多的 DDL。当然,DDL 语句的必要性使部署更加复杂。但是无论如何,您都需要能够处理这件事。但确实,
AttributeConverter
在这种情况下,您不需要任何 DDL,因为您只需将另一个值放在同一列中,除了值的最大长度之外没有任何特殊约束。这假设您对列没有检查约束来限制合法值。- 您是否必须记录数据库中存储的值之间的关系
Enum
?取决于你的团队。DBA 是否关心数据的含义?DBA 是否具有理解 Java 代码的访问权限和技能?如果 DBA 需要或想知道并且不能或不会从源代码中获取信息,则必须将其记录在案。真的。
- 您是否必须记录数据库中存储的值之间的关系
推荐阅读
- java - 帮助弹出菜单
- angular - 在html页面中显示数据需要时间
- reactjs - reduxForm() 使用没有酶的 Jest 连接 React 组件单元测试
- docker - GitLab SSH 到服务器以运行 docker stack deploy,找不到文件
- javascript - 在 c3js 中为双轴定制工具提示
- c# - 带有任何参数的 Nsubstitute 模拟方法都不起作用.net核心
- python - 如何正确使用测距工具?
- python - 按熊猫系列中的两列排序
- javascript - Bootstrap 中的子菜单下拉布局
- python - 不从列表中获取值的函数