我想描述在 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
}
然后是new record is inserted in DB as follows
:
@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
枚举常量放在之后 ITALIC
的明显解决方案)?
编辑 1:显然,出于明显的性能原因,我不想EnumType.STRING
在我的数据库中存储字符串(请参阅 参考资料),即数据检索和存储性能会受到严重影响!