java - 在域模型中的 JPA 拼写灾难的上下文中天真地使用 java 枚举的序号

标签 java hibernate jpa enums ordinals

我想描述一个在在 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/

相关文章:

java - 如何在hibernate中检查不同id的相同数据是否存在?

java - Hibernate 4.3.9 和映射枚举

java - @Query注解不填充和执行参数

java - Kundera-Cassandra 无法为具有 MappedSuperClass 的实体映射复合键

java - Android API 中的 'focus' 是什么?

java - 构建 Maven 时如何覆盖远程资源?

java - 使用 XML 而不是通过注释配置 hibernate 有充分的理由吗?

java - hibernate OGM : Having trouble starting MongoDB database

java - 如何防止jar反编译

java - Hibernate查询语言: Getting a SQL Syntax Error for my Query