6

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)。

这真的是一个错误/限制,还是我错过了一些配置选项等,从而可以使用“非空默认”列?

4

1 回答 1

10

您在这里发现了几件事(都与 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 与插入 DEFAULT UpdatableRecord

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

在我看来,这是一个错误。jOOQ 的 CRUD 操作应该是DEFAULT值安全的。store()只有那些在//操作之前明确设置的值才应该在生成的 SQL 中呈现insert()update()我为此注册了#2698

通过以下方式插入 NULL 与插入 DEFAULT DAO

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

不错的收获。这对于解决/增强来说并非易事,因为 POJO 不附带每列的内部“已更改”/“脏”标志。因此不可能知道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 中的上述元数据
于 2013-08-17T08:46:57.870 回答