@ColumnDefault 的 HIbernate 列不能为空

Posted

技术标签:

【中文标题】@ColumnDefault 的 HIbernate 列不能为空【英文标题】:HIbernate Column with @ColumnDefault cannot be null 【发布时间】:2018-09-11 13:07:26 【问题描述】:

我的应用程序通过 Spring Boot 使用休眠。

我已经创建了一个这样的表:

public class TopicSubscriberMap implements Serializable
   
    @ColumnDefault(value="'pending'")
    @Column(nullable=false)
    private String status;
    ...

表在mysql中创建如下:

mysql> desc topic_subscriber_map;
+---------------+--------------+------+-----+---------+-------+
| Field         | Type         | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+-------+
| status        | varchar(255) | NO   |     | pending |       |
+---------------+--------------+------+-----+---------+-------+

像这样保存表格:

TopicSubscriberMap tsm = new TopicSubscriberMap();
tsm = mapRepository.save(tsm);

我收到一个错误:

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

如果我使该字段可以为空,那么虽然表正在保存,但在数据库中,

+--------+
| status | 
+--------+
| NULL   | 
+--------+

为什么@ColumnDefault 不起作用?我的错在哪里?

编辑: 当我删除 @ColumnDefault 并将列声明为

private String status = "pending"

那么虽然默认值确实有效,但表架构显示:

+---------------+--------------+------+-----+---------+-------+
| Field         | Type         | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+-------+
| status        | varchar(255) | NO   |     | NULL    |       |
+---------------+--------------+------+-----+---------+-------+

如何使默认值起作用并在表架构中显示它?

【问题讨论】:

set default value in hibernate此链接将有助于解决您的问题 【参考方案1】:

因此,您在这里使用了 2 种不同的设置默认值的方法:通过 DB 和通过 Java。两种方法都不会相互协调,如果配置了另一种方法,则一种方法不受影响。我会解释的。

您对@ColumnDefault 使用的第一种方法是DB 方法。使用@ColumncolumnDefinition 属性可以实现相同的行为。在这里,JPA 只是将此值添加到 DB 中字段的列定义中。但是,Hibernate 在准备查询时不考虑 DB 定义,并将空值从 Java 对象转录到其准备好的 SQL 查询中,从而导致查询执行时出现MySQLIntegrityConstraintViolationException。更多信息在这里:Hibernate Guide

您使用的第二种方法依赖于 Java 初始化。当您调用new TopicSubscriberMap(); 时,您的实体对象获得了默认值。但是您的数据库不知道或不关心它,因为它的列定义没有受到影响。

解决方案

如果您想在 DB 上设置默认值并能够在应用程序中使用它们,您可以使用 Hibernate 的 @DynamicInsert 注释

@DynamicInsert
public class TopicSubscriberMap implements Serializable
   
    @ColumnDefault(value = "pending")
    // alternately @Column(columnDefinition = "VARCHAR(255) DEFAULT 'pending'")
    private String status;
    ...

这将解决您的两个问题,尽管在某些情况下它会带来自己的一组性能问题,在此线程中谈到:Why does Hibernate set dynamic insert=false by default

【讨论】:

以上是关于@ColumnDefault 的 HIbernate 列不能为空的主要内容,如果未能解决你的问题,请参考以下文章

6.Spring+Struts+Hibernat注解方式整合

Hibernat 原生SQL运行结果集处理方法

请说说你对Hibernat的理解?JDBC和Hibernate各有什么优势和劣势?

springboot 问题

jpa_缓存

解析ThreadLocal