Hibernate Tools (hbm2java): Column Default Value is Missing



我正在使用hbm2java,这是Hibernate工具的一部分,将数据库反向工程为JPA实体类。

我通过./mvnw clean generate-sources运行工具,生成实体类并保存到target/generated-sources

UserAccount数据库表中,Created列定义如下:注意默认值:

Created TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,

当hbm2java对该列进行反向工程时,不包含默认值:

...
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "CREATED", nullable = false, length = 29)
public Timestamp getCreated() {
return this.created;
}
public void setCreated(Timestamp created) {
this.created = created;
}
...

因此,当试图将UserAccount实体保存到数据库时,会抛出DataIntegrityViolationException:

org.springframework.dao。DataIntegrityViolationException:过的非null的属性引用空值或瞬态值:com.example.UserAccount.created

真的希望有一种方法,因为我有相当多的数据库列与默认值,最复杂的是:

DEFAULT 'User' + CAST(NEXT VALUE FOR SeqUserAccountUsername as VARCHAR(19))

…它只生成一个字符串,如User13.

我还在学习Spring Boot和Hibernate,需要一些建议来解决这个问题。

我目前的研究:

  • 同样的问题早在2007年Hibernate论坛上就有人问过,但没有提供解决方案。
  • 本文档讨论了如何使用"default-value"属性设置"字段的默认初始化值"。这是正确的方法吗?

相信下面的映射应该可以在所有最新的Hibernate版本中工作:

@Generated(INSERT)
@ColumnDefault("CURRENT_TIMESTAMP")
@Column(nullable = false)
public Timestamp getCreated() {
return this.created;
}

如果不行,告诉我。

(当然,逆向工程工具不知道任何默认值)

首先,您需要找到能够阐明该数据库如何工作的人。问题是像TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL这样的SQL列定义意味着:

  • 你从不选择null
  • 不能插入/set null
  • 你可以插入/set not null
  • 您可以在DML语句中省略列或指定DEFAULT,在这种情况下,DB根据默认表达式(在您的情况下是CURRENT_TIMESTAMP)生成值

使完全相同的最简单的选项Hibernate的功能/能力,是使用JPA回调,史密斯。如:

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "CREATED", nullable = false, /* updatable = false, */ length = 29)
public Timestamp getCreated() {
return this.created;
}
@PrePersist
protected void onPrePersist() {
if (this.created == null) {
this.created = Timestamp.from(Instant.now());
}
}

允许您指定任意创建的时间戳,并且只有当它是nullHibernate时才会使用当前时间-这正是DB允许您做的。

其他选项做类似的事情,但不一样,但其中一些可能适合你。

  1. @CreationTimestamp:
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "CREATED", nullable = false, length = 29)
public Timestamp getCreated() {
return this.created;
}

它忽略this.created的值,并插入当前时间,在Java端计算,到DB。

  1. @Generated(GenerationTime.INSERT)
@Generated(GenerationTime.INSERT)
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "CREATED", nullable = false, length = 29)
public Timestamp getCreated() {
return this.created;
}

它忽略this.created的值,并将值的生成委托给DB,基本上它省略了INSERT语句中相应的列(嗯…"generate">

如果您选择使用@CreationTimestamp@Generated(GenerationTime.INSERT),请删除相应的settervoid setCreated(Timestamp created),以避免created字段的可变性。

最新更新