我想描述一个在在 JPA 实体的上下文中天真地使用 Java 枚举时发生的令人讨厌的问题。让我们来看看这个问题是如何发生的。
首先是领域模型:
假设我有一个 Text
JPA 实体,它代表一段文本(小说、新闻文章等)。这是 JPA 实体:
@Entity
public class Text {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Version
@Column(name = "version")
private Integer version;
private String content;
@Enumerated
@ElementCollection
private Set<Style> styles;
//Setters and getters omitted.
对于 Text
的实例,可以应用一种或多种样式,例如斜体、粗体等。样式表示为 java 枚举。
首先,我们假设应用程序使用以下枚举开始其生命:
public enum Style {
BOLD, ITALIC
}
下面的测试将在关系数据库中插入以下行:
集成测试:
@Test
@Rollback(value=false)
public void inEarlyLifePersist() {
Text text =new Text();
text.setContent("This is my beautiful novel...");
text.setStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
text.persist();
}
文本表中的数据:
# id, content, version
11, This is my beautiful novel..., 0
*text_style表中的数据:*
# text, styles
11, 0
11, 1
然后,稍后,一些不明智的开发人员决定添加新样式:STRIKE_THROUGH
到我们的Style
枚举中放置这个新枚举常量/值作为第一个:
public enum Style {
STRIKE_THROUGH, BOLD, ITALIC
}
然后一个新记录被插入到数据库中如下
:
@Test
@Rollback(value=false)
public void afterChangeToEnumPersist() {
Text text =new Text();
text.setContent("This is my beautiful short story...");
text.setStyles(EnumSet.of(Style.STRIKE_THROUGH, Style.BOLD));
text.persist();
}
在文本表格中:
# id, content, version
14, This is my beautiful short story..., 0
并且 *在 text_style 表中:*
# text, styles
14, 0
14, 1
很明显,领域模型现在已经严重受损!
我的问题是有什么可能的策略可以避免域中的拼写灾难,如上述情况(除了放置 STRIKE_THROUGH 的明显解决方案
枚举常量 after ITALIC
)?
编辑 1:显然我不想在我的数据库中存储字符串(参见 EnumType.STRING
),这是出于明显的性能原因,即数据检索和存储性能会受到严重影响受影响!
最佳答案
您需要像下面这样重新定义您的enum
。
public enum Style {
STRIKE_THROUGH(2), BOLD(0), ITALIC(1)
Style(int code){
this.code=code;
}
}
并实现 Hibernate User type保留代码
。
关于java - 在域模型中的 JPA 拼写灾难的上下文中天真地使用 java 枚举的序号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19003307/