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

时间:2020-12-18 12:33:25

It seems that JOOQ is completely ignoring the default values of database columns. Neither gets the ActiveRecord object updated nor does it skip this column on INSERT. Instead it tries to set it to NULL which fails on NOT NULL columns.

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

Example:

例:

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

The behaviour I would expect is that either the newRecord() initializes all default variables with the korrekt values (although I understand that this could be difficult if the result is the outcome of a custom function :-)).or that the INSERT INTO does not insert all unmodified columns with default values and then that the INSERT INTO is followed by a SELECT that fetches the now existing values from the database (similar to a RETURNING).

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

Is this really a bug/limitation or am I missing some config option etc which makes it possible to use "not null default" columns?

这真的是一个错误/限制,还是我错过了一些配置选项等,这使得可以使用“not null default”列?

1 个解决方案

#1


9  

You've spotted a couple of things here (all relevant to jOOQ 3.1 and previous versions):

你在这里发现了一些东西(都与jOOQ 3.1和以前的版本有关):

Returning default values from inserts:

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

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

That would be a nice-to-have feature, indeed. Currently, jOOQ only fetches IDENTITY column values. You can use the INSERT .. RETURNING syntax or the UPDATE .. RETURNING syntax to explicitly chose which columns ought to be returned after an insert or update. But being able to do so in regular CRUD operations would be much better.

事实上,这将是一个很好的功能。目前,jOOQ仅提取IDENTITY列值。您可以使用INSERT .. RETURNING语法或UPDATE .. RETURNING语法显式选择在插入或更新后应返回哪些列。但是能够在常规CRUD操作中这样做会好得多。

This had also been mentioned in this thread. The relevant feature request for this is #1859.

在这个帖子中也提到了这一点。相关的功能请求是#1859。

You can work around this issue by calling

您可以通过致电解决此问题

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

Inserting NULL vs. inserting DEFAULTs through UpdatableRecord:

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

This is a bug, in my opinion. jOOQ's CRUD operations should be DEFAULT value safe. Only those values that have been set explicitly prior to a store() / insert() / update() operation ought to be rendered in the generated SQL. I have registered #2698 for this.

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

Inserting NULL vs. inserting DEFAULTs through DAO:

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

Nice catch. This is non-trivial to solve / enhance, as a POJO does not ship with an internal "changed" / "dirty" flag per column. It is thus not possible to know the meaning of a null reference in a POJO.

很好听。这对于解决/增强来说并不重要,因为POJO每列没有内部“更改”/“脏”标记。因此,不可能知道POJO中空引用的含义。

On the other hand, jOOQ already knows whether a column is nullable. If jOOQ also maintained metadata about the presence of a DEFAULT clause on a column, it could deduce that the combination NOT NULL DEFAULT would have to lead to:

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

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

And to

UPDATE bug SET bar = DEFAULT WHERE foo = 3

I have registered

我已经注册了

  • #2699: Adding some metadata information to generated code
  • #2699:向生成的代码添加一些元数据信息
  • #2700: Leveraging the above metadata in SQL from DAOs
  • #2700:从DAO中利用SQL中的上述元数据

#1


9  

You've spotted a couple of things here (all relevant to jOOQ 3.1 and previous versions):

你在这里发现了一些东西(都与jOOQ 3.1和以前的版本有关):

Returning default values from inserts:

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

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

That would be a nice-to-have feature, indeed. Currently, jOOQ only fetches IDENTITY column values. You can use the INSERT .. RETURNING syntax or the UPDATE .. RETURNING syntax to explicitly chose which columns ought to be returned after an insert or update. But being able to do so in regular CRUD operations would be much better.

事实上,这将是一个很好的功能。目前,jOOQ仅提取IDENTITY列值。您可以使用INSERT .. RETURNING语法或UPDATE .. RETURNING语法显式选择在插入或更新后应返回哪些列。但是能够在常规CRUD操作中这样做会好得多。

This had also been mentioned in this thread. The relevant feature request for this is #1859.

在这个帖子中也提到了这一点。相关的功能请求是#1859。

You can work around this issue by calling

您可以通过致电解决此问题

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

Inserting NULL vs. inserting DEFAULTs through UpdatableRecord:

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

This is a bug, in my opinion. jOOQ's CRUD operations should be DEFAULT value safe. Only those values that have been set explicitly prior to a store() / insert() / update() operation ought to be rendered in the generated SQL. I have registered #2698 for this.

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

Inserting NULL vs. inserting DEFAULTs through DAO:

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

Nice catch. This is non-trivial to solve / enhance, as a POJO does not ship with an internal "changed" / "dirty" flag per column. It is thus not possible to know the meaning of a null reference in a POJO.

很好听。这对于解决/增强来说并不重要,因为POJO每列没有内部“更改”/“脏”标记。因此,不可能知道POJO中空引用的含义。

On the other hand, jOOQ already knows whether a column is nullable. If jOOQ also maintained metadata about the presence of a DEFAULT clause on a column, it could deduce that the combination NOT NULL DEFAULT would have to lead to:

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

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

And to

UPDATE bug SET bar = DEFAULT WHERE foo = 3

I have registered

我已经注册了

  • #2699: Adding some metadata information to generated code
  • #2699:向生成的代码添加一些元数据信息
  • #2700: Leveraging the above metadata in SQL from DAOs
  • #2700:从DAO中利用SQL中的上述元数据