【问题标题】:Default value declared in JPA @Column( columnDefinition ... ) not set when persisted持久化时未设置 JPA @Column(columnDefinition ...) 中声明的默认值
【发布时间】:2019-06-01 12:59:55
【问题描述】:

我的 Java 实体中有这样的属性:

@Basic(fetch = FetchType.LAZY) //I tried without this as well
@Column(name = "value_x", columnDefinition = "bigint default 0")
private Long valueX;

在 pgAdmin 的表定义中我看到:

value_x bigint DEFAULT 0,

但是当插入对象时(此属性为空),列为空/空,没有插入 0 值。

有人会知道为什么它不插入默认值吗?使用 EclipseLink。

【问题讨论】:

  • JPA 提供程序不使用默认值,除非在创建表时使用。如果你想在里面放一个 0,那么在你的类中设置该字段

标签: postgresql jpa jakarta-ee entity eclipselink


【解决方案1】:

空值是因为如果没有实施特殊处理,JPA 会在该列中显式插入 null 值。 columnDefinition 确实使用 DEFAULT 创建列,但它不会让 JPA 意识到/或在之后遵守它。

它是一个可以为空的列,所以没有错误。看看在普通 SQL 中会发生什么,想想这张表:

create table example (
    col1 bigint default 42,
    col2 bigint default 99
);

然后进行如下插入:

insert into example (col1) values (null);

然后选择:

select * from example;

会显示如下结果:

col1 | col2
------+------
(空) | 99

如果你需要在 java 端管理默认值,你需要在 Java 端做一些特殊的东西。

例如参见this question 并注意接受的答案不是有效的答案,而是this answer。所以在类实例化时设置值:

private Long valueX = 0;

另一种方法是this answer for different question 建议,使用@PrePersist

@PrePersist
void prePersist() {
    if (this.valueX == null)
       this.valueX = 0;
}

【讨论】:

  • 谢谢,它的工作原理,如果我理解正确这两种解决方案呈现相同的输出? (经过测试,似乎表现相同)
  • 是的。唯一的区别是 @PrePersist 是一种 lazy 初始化,它是在 JPA 持久化之前完成的。这可能取决于哪种情况更合适。
  • 我很清楚地设置了这个值,因为它更干净,但是如果一次创建大量条目但在不同时间持续存在(并且属性可能更大),我可以看到优势在 prePersist 中。
【解决方案2】:

我找到了解决相同问题的另一种方法,因为当我创建自己的对象并保存在数据库中并且不尊重具有默认值的 DDL 时。

所以我查看了我的控制台,生成了 SQL,发现 insert 带有所有字段,但我的对象中只有一个属性的值发生了变化。

所以我在模型类中放了这个注解。

@DynamicInsert

在插入数据时,框架不插入空值或未修改的值,使得插入时间更短。

还有@DynamicUpdate注解。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-22
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    • 1970-01-01
    • 2011-11-20
    相关资源
    最近更新 更多