我的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
映射到enum UserStatus
以限制持久层本身的整体。
public enum UserStatus {
ACTIVE,
PENDING,
DEACTIVATED,
BLOCKED,
DELETED,
SPAM
}
我想知道使用这种方法在持久层中实现数据库枚举有什么缺点吗?我抛弃了多篇推荐使用AttributeConverter的文章,但是由于枚举中的值非常有限且修改的机会较小,因此我无法将所有这些文章与我的要求联系起来。
我是否缺少某些东西,或者可以对我的设计进行任何改进?
我丢掉的文章:
vladmihalcea
thorban和其他一些stackoverflow问题。
更新:阅读了Jens的回答后,我决定实施AttributeConverter
(针对用户gender
)。那让我有些困惑:
为什么我决定将枚举用作MYSQL列类型:因为它限制了值并需要较少的空间。由于MYSQL将枚举的序数值存储在幕后,并且当要求该值表示字符串的String值时,可以节省空间。
我对性别的实现:
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
是邪恶的,因为总有一天,如果我需要向enum列中添加额外的值,这将需要一个表ALTER,但使用{{ 1}}?因为我们还使用了AttributeConverter
,如果有一天需要新的性别,是否需要更改?
2.如果使用java enum
,则必须在某处记录Java AttributeConverter
(此处为enum
)的解释,以便DBA能够理解F,M,O的含义。我在这里吗?
答案 0 :(得分:2)
文章为您提供了许多潜在的弊端:
使用@Enumerated(EnumType.STRING)
具有以下功能:
如果您不能处理大量数据(对于这些数据而言,更新所有行的列是一个实际问题),那么我不会费力。当简单的解决方案实际上成为问题时,引入AttributeConverter
并更新数据就很容易了。
我不认为任何东西都是“邪恶的”,因为它可能需要ALTER TABLE
语句。通过这种说法,我们应该完全废除关系数据库,因为使用关系数据库需要DDL,而应用程序的演进将需要更多的关系数据库。当然,DDL语句的必要性使部署更加复杂。但是无论如何,您都需要能够处理此问题。
但是的确,在这种情况下,使用AttributeConverter
不需要任何DDL,因为您只需要在同一列中放入另一个值即可,除了最大长度,该值没有任何特殊约束价值。假设您在该列上没有检查约束来限制合法值。
Enum
与数据库中存储的值之间的关系?取决于您的团队。 DBA甚至关心数据的含义吗? DBA是否具有访问权限和掌握Java代码的技能?如果DBA需要或想要知道并且无法或不会从源代码中获取信息,则必须对其进行记录。是的。