Jooq的存储功能未使用默认值

时间:2018-10-30 09:28:12

标签: java postgresql jooq

我尝试存储具有以下约束的try对象:

ALTER TABLE ATTEMPT ADD COLUMN files json NOT NULL DEFAULT '{}'::json;

和代码:

AttemptRecord attemptRecord = context.newRecord(T_ATTEMPT, attempt);
setAttemptId(attempt.getId());
store();

但是当我用Jooq存储它时,出现以下错误:

nested exception is org.postgresql.util.PSQLException: ERROR: null value in column "files" violates the not-null constraint

在此之前,我有一个bytearray列,而不是json文件列,在默认值下一切正常。 我也使用调试器工具,并且AttemptRecord包含此文件值,这听起来很奇怪,但是我不知道这是什么意思。

{NullNode@3189} "null"

这不是真正的null,就像JsonNode为null一样。

为什么Jooq忽略默认值?

1 个答案:

答案 0 :(得分:1)

说明:

问题出在你的电话上

AttemptRecord attemptRecord = context.newRecord(T_ATTEMPT, attempt);

Consider the Javadoc

  

结果记录将其所有值的内部“已更改”标志设置为true。

您的attempt POJO无法区分

  • 具有SQL null语义的DEFAULT
  • 具有SQL null语义的NULL

因此,您通过传递POJO(依次调用每一列的记录设置程序)来积极设置files列的值这一事实,最合理的默认行为是设置该列的changed()的{​​{1}}标志,因此假定您要向数据库发送true值。

如果不是这种情况,将会有很多SQL功能无法有效使用,例如一些触发器仅在要插入/更新的某些列上触发。

我最近也在博客文章https://blog.jooq.org/2018/11/05/how-to-use-jooqs-updatablerecord-for-crud-to-apply-a-delta/

中对此进行了记录。

解决方法:仅在一种情况下解决此问题:

在这种情况下,解决方法是使用以下命令为null列重置changed()标志:

files

解决方法:针对所有attemptRecord.changed(ATTEMPT.FILES, false); 方法调用解决此问题

一个更彻底的解决方案是实现一个RecordListener,它会在您每次运行store()store()insert()调用之前触发,从而使您可以打补丁正在存储的记录。

此处有更多信息:https://www.jooq.org/doc/latest/manual/sql-execution/crud-with-updatablerecords/crud-record-listener