我想从一个表中选择所有字段,获取另一个表的记录,然后将记录插入该表中。但是,我收到一个错误,指出值为null。以下是相关的代码:
// Fetch
PersonDeactivatedRecord person = getContext().selectFrom(PERSON)
.where(PERSON.ID.eq(id))
.fetchOneInto(PersonDeactivatedRecord.class);
// Insert
person.setDeactivatedOn(new Timestamp(System.currentTimeMillis()));
getContext().insertInto(PERSON_DEACTIVATED)
.set(person)
.execute();
person_deactivated
表是person
表的副本加上一列(deactivated_on)。我得到的错误是:
org.jooq.exception.DataAccessException: SQL [insert into "xxx"."person_deactivated" ("deactivated_on") values (cast(? as timestamp))]; ERROR: null value in column "id" violates not-null constraint
Detail: Failing row contains (null, null, null, null, null, null, null, null, null, ...)
请注意,当我调试此代码时,我看到person
对象已按预期完全填充。知道我在这里缺少什么吗?
答案 0 :(得分:2)
InsertSetStep.set(Record)
方法不会将整个person
记录插入目标表中,而只考虑其值为“已更改”的字段。见Javadoc:
这与调用
set(Map)
并将参数记录视为Map<Field<?>, Object>
相同,除了考虑Record.changed()
标志以便仅更新更改的值。
所以,你有几种方法可以解决这个问题(当然,这里列出的不止一些):
这将是最简单的修复:
// Insert
person.setDeactivatedOn(new Timestamp(System.currentTimeMillis()));
person.changed(true); // Sets all flags to true
getContext().insertInto(PERSON_DEACTIVATED)
.set(person)
.execute();
此解决方案的优点是您只有一个查询,这意味着:
所以,你可以写:
getContext()
.insertInto(PERSON_DEACTIVATED)
.columns(PERSON_DEACTIVATED.fields())
.select(
select(Arrays
.stream(PERSON_DEACTIVATED.fields())
.map(f -> f.equals(PERSON_DEACTIVATED.DEACTIVATED_ON)
? currentTimestamp()
: PERSON.field(f))
.collect(Collectors.toList()))
.from(PERSON)
.where(PERSON.ID.eq(id))
)
.execute();
与往常一样,此答案假设您的代码中包含以下静态导入:
import static org.jooq.impl.DSL.*;
上述查询会将PERSON
中的所有列插入PERSON_DEACTIVATED
,但DEACTIVATED_ON
列将替换为当前时间戳。