【问题标题】:Spring JPA - default value for enum field in enumSpring JPA - 枚举中枚举字段的默认值
【发布时间】:2015-08-22 19:54:35
【问题描述】:

我们有一个带有枚举字段的实体 - emailCommunicationStatus,我们想使用 JPA 注释为它设置一个默认值 - 'UNKNOWN'

但是,当我们将实体保存到数据库时,该字段的值是 null 而不是 。对于布尔字段 - isLocked,保存正确的默认值 (false)。

@Entity
public class Account {

    @Id
    @GeneratedValue
    @Column(name = "id")
    protected Long id;

    @Column(columnDefinition = "boolean default false")
    private boolean isLocked;

    @Column(length = 32, columnDefinition = "varchar(32) default 'UNKNOWN'")
    @Enumerated(value = EnumType.STRING)
    private CommunicationStatus emailCommunicationStatus;

    PlayerAccount() {
        super();
    }
}

public enum CommunicationStatus {
    VALID,
    INVALID,
    DONT_CONTACT,
    UNKNOWN;
}

如果我们改为使用:@Column(length = 32, columnDefinition = "varchar(32) default 'UNKNOWN'") for emailCommunicationStatus,我们会在保存时收到以下异常:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'emailCommunicationStatus' cannot be null

我们做错了什么?为什么它只对布尔值起作用?

【问题讨论】:

    标签: java spring hibernate jpa enums


    【解决方案1】:

    只需初始化 Entity 字段。 Hibernate 将使用已设置的值实例化实体类。当它刷新时,该字段将插入指定的值。

    private CommunicationStatus emailCommunicationStatus = CommunicationStatus.UNKNOWN;
    

    问候

    【讨论】:

    • 这种方法有个缺点。如果您查看表 SQL 定义,您将不会在其中看到任何默认值。因此,如果您用 null 覆盖它们,实体将被保存而不会出现任何错误。 more details
    【解决方案2】:

    当某些 SQL 代码插入一行而不为 emailCommunicationStatus 列指定任何值时,您所做的很有用。在这种情况下,该行将具有“未知”作为该列的值:

    insert into account (id, isLocked) values(1, false)
    

    但是 Hibernate 永远不会做这样的插入。它将始终传递此实体的emailCommunicationStatus 字段的实际值。因此,如果您将其保留为 null,它将在数据库中显式地将其设置为 null:

    insert into account (id, isLocked, emailCommunicationStatus) values(1, false, null)
    

    你想要的是设置这个字段的默认值:

    @Column(length = 32, columnDefinition = "varchar(32) default 'UNKNOWN'")
    @Enumerated(value = EnumType.STRING)
    private CommunicationStatus emailCommunicationStatus = CommunicationStatus.UNKNOWN;
    

    它适用于 isLocked,因为布尔字段的默认值为 false。

    【讨论】:

      【解决方案3】:

      除了添加列定义之外,您还可以设置动态查询。但也要检查下面的 cmets,因为这种方法似乎不受欢迎。

      如果您使用的是休眠版本 注释您的实体

      @org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true)
      

      当 dynamic-insert 属性设置为 true 时,Hibernate 会 不包括属性的空值(对于未设置的属性 由应用程序)在 INSERT 操作期间。随着 dynamic-update 属性设置为 true,Hibernate 不包括 UPDATE 操作中未修改的属性。

      对于 > 4 的休眠版本,您应该改用 @DynamicUpdate。在 java 代码中初始化也是一个很好的建议。

      【讨论】:

      • 你确定这行得通吗?看起来 OP 的表有一个不允许空值的约束。如果你 INSERT 一些东西并且仍然没有明确地给列一个值,它仍然是 null。
      • 也许我应该改写一下,我的意思是结合使用列定义和设置动态查询,将编辑答案
      • 这是一个糟糕的解决方案:现在数据库将具有 'UNKNOWN' 作为值,但内存中的实体仍将具有 null。 Hibernate 文档不鼓励使用动态插入和更新。
      • 我也建议在代码中进行设置,这可能是一个开销,因为你是对的,在代码中设置就足够了,在我看来,仍然将注意力转移到动态更新结构上还不错
      • The Hibernate documentation discourages the usage of dynamic inserts and updates. 这是我不知道的,我实际上认为这是一种推荐的方式,因为该结构仅适用于这种情况。我会留下答案,并用不好的做法评论编辑它
      猜你喜欢
      • 2011-10-27
      • 1970-01-01
      • 1970-01-01
      • 2016-05-08
      • 2016-10-10
      • 2011-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多