我的应用程序在Spring Boot中使用了hibernate。
我创建了一个这样的表:
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
如果我将字段设为可为空,那么虽然该表已被保存,但在db中,
+--------+
| status |
+--------+
| NULL |
+--------+
为什么@ColumnDefault不起作用?我的错误在哪里?
修改 当我删除@ColumnDefault并将列声明为
时private String status = "pending"
然后虽然默认值有效,但表架构显示:
+---------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+-------+
| status | varchar(255) | NO | | NULL | |
+---------------+--------------+------+-----+---------+-------+
如何使默认值有效并将其显示在表架构中?
答案 0 :(得分:0)
因此,您在这里使用2种不同的方法来设置默认值:通过DB和通过Java。两种方法都不相互协调,并且如果配置了其他方法,则一种方法不会受到影响。我会解释。
与@ColumnDefault
一起使用的第一种方法是 DB方法。使用columnDefinition
的{{1}}属性可以实现相同的行为。在这里,JPA只需将此值添加到DB中字段的列定义中。但是,Hibernate在准备查询时不考虑数据库定义,而是将null值从Java对象转录为准备好的SQL查询,导致查询执行时@Column
。有关更多信息,请点击此处:Hibernate Guide
您使用的第二种方法依赖于 Java初始化。当您调用MySQLIntegrityConstraintViolationException
时,您的实体对象将获得默认值。但是您的数据库不知道或不关心它,因为它的列定义没有受到影响。
如果要在数据库上设置默认值,并且还可以在应用程序中使用它们,则可以使用Hibernate的new TopicSubscriberMap();
批注
@DynamicInsert
这将解决您的两个问题,尽管在某些情况下会带来一系列性能问题,这些问题在此线程中讨论:Why does Hibernate set dynamic insert=false by default