一尘不染

JOOQ忽略具有默认值的数据库列

sql

看来,JOOQ完全忽略了数据库列的默认值。既不会更新ActiveRecord对象,也不会跳过INSERT上的此列。相反,它尝试将其设置为NULL,这在NOT
NULL列上失败。

例子:

CREATE TABLE bug (
  foo int,
  bar int not null default 42
);

  BugRecord b = jooq.newRecord(BUG);
  b.setFoo(3);
  b.store();

  assertNotNull(b.getBar()); // fails

  Record r = jooq.select().from(BUG).fetchOne();
  assertEquals(new Integer(-1), r.getValue(BUG.BAR)); // fails

  // DataMapper pattern
  Bug b = new Bug();
  b.setFoo(3);
  bugDao.insert(b); // Fails because it tries to set "bar" to NULL

我期望的行为是newRecord()使用korrekt值初始化所有默认变量(尽管我知道如果结果是自定义函数的结果可能很困难:-)。或者INSERT
INTO可以而不是使用默认值插入所有未修改的列,然后在INSERT
INTO之后执行SELECT,该SELECT从数据库中获取现有值(类似于RETURNING)。

这真的是错误/限制吗?还是我缺少某些配置选项等,因此可以使用“非空默认值”列?


阅读 163

收藏
2021-05-23

共1个答案

一尘不染

您在这里发现了几件事(都与jOOQ 3.1和以前的版本有关):

从插入中返回默认值:

BugRecord b = jooq.newRecord(BUG);
b.setFoo(3);
b.store();

assertNotNull(b.getBar()); // fails

确实,这将是一个不错的功能。当前,jOOQ仅获取IDENTITY列值。您可以使用一种INSERT .. RETURNING或多种UPDATE .. RETURNING语法来明确选择在插入或更新后应返回哪些列。但是能够在常规CRUD操作中做到这一点会更好。

这个线程中也提到了这一点。与此相关的功能要求是#1859

您可以通过以下方式解决此问题:

b.refresh();             // Refresh all columns
b.refresh(BUG.BAR, ...); // Refresh only some columns

插入NULL与通过UpdatableRecord以下方式插入默认值:

Record r = jooq.select().from(BUG).fetchOne();
assertEquals(new Integer(-1), r.getValue(BUG.BAR)); // fails

我认为这是一个错误。jOOQ的CRUD操作应具有DEFAULT价值安全性。只有那些已经设置一个明确前值store()/
insert()/update()操作应在生成的SQL被渲染。我已经为此注册了#2698

插入NULL与通过DAO以下方式插入默认值:

// DataMapper pattern
Bug b = new Bug();
b.setFoo(3);
bugDao.insert(b); // Fails because it tries to set "bar" to NULL

不错的收获。解决/增强功能并非易事,因为POJO并未在每列中附带内部“ changed” /“
dirty”标志。因此,不可能知道nullPOJO中引用的含义。

另一方面,jOOQ已经知道列是否可为空。如果jOOQ还维护有关DEFAULT列中子句存在的元数据,则可以推断出该组合NOT NULL DEFAULT将导致:

INSERT INTO bug(foo, bar)
VALUES(3, DEFAULT)

UPDATE bug SET bar = DEFAULT WHERE foo = 3

我已经注册

  • #2699:将一些元数据信息添加到生成的代码中
  • #2700:从DAO中利用SQL中的上述元数据
2021-05-23