我尝试存储具有以下约束的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忽略默认值?
答案 0 :(得分:1)
问题出在你的电话上
AttemptRecord attemptRecord = context.newRecord(T_ATTEMPT, attempt);
结果记录将其所有值的内部“已更改”标志设置为true。
您的attempt
POJO无法区分
null
语义的DEFAULT
值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