使用 jOOQ 从具有正确类型转换的值() 中选择插入
我使用 jOOQ 将相当多的行插入到一个多对多关系的表中。代码工作,生成的SQL符合预期,我的问题是我希望jOOQ代码可以更简单。
我有一个简化的结构(所有内容都重命名了,删除了大多数字段,删除了大多数约束,它只是一个愚蠢但准确的结构示例):
CREATE TABLE person (
person_id BIGSERIAL PRIMARY KEY,
person_name VARCHAR(64) NOT NULL UNIQUE
);
CREATE TABLE company (
company_id BIGSERIAL PRIMARY KEY,
company_name VARCHAR(100) NOT NULL UNIQUE
);
CREATE TABLE employment_contract (
company_id BIGINT NOT NULL REFERENCES company,
person_id BIGINT NOT NULL REFERENCES person,
PRIMARY KEY (company_id, person_id),
salary INT NOT NULL,
creation_date_time TIMESTAMP NOT NULL
);
我的插入代码:
Table<Record4<String, String, Integer, Timestamp>> insertValues = values(
row(
cast(null, COMPANY.COMPANY_NAME),
cast(null, PERSON.PERSON_NAME),
cast(null, EMPLOYMENT_CONTRACT.SALARY),
cast(null, EMPLOYMENT_CONTRACT.CREATION_DATE_TIME)
)
).as("insert_values",
COMPANY.COMPANY_NAME.getName(), -- these lines are bugging me
PERSON.PERSON_NAME.getName(),
EMPLOYMENT_CONTRACT.SALARY.getName(),
EMPLOYMENT_CONTRACT.CREATION_DATE_TIME.getName()
);
Insert<AffectedSubscriberRecord> insert = insertInto(EMPLOYMENT_CONTRACT)
.columns(EMPLOYMENT_CONTRACT.COMPANY_ID,
EMPLOYMENT_CONTRACT.PERSON_ID,
EMPLOYMENT_CONTRACT.SALARY,
EMPLOYMENT_CONTRACT.CREATION_DATE_TIME
)
.select(
select(
COMPANY.COMPANY_ID,
PERSON.PERSON_ID,
insertValues.field(EMPLOYMENT_CONTRACT.SALARY),
insertValues.field(EMPLOYMENT_CONTRACT.CREATION_DATE_TIME)
)
.from(insertValues)
.join(COMPANY).using(COMPANY.COMPANY_NAME)
.join(PERSON).using(PERSON.PERSON_NAME)
);
然后,我将所有行绑定到并执行该事物。我确定引用的键已经存在,并且原始代码也解决了重复项,我们在这里不需要关心这些事情。context.batch(insert)
person
company
困扰我的是表 - 我需要在容易出错的复制粘贴中两次指定列类型和名称,使用模糊整个代码并且容易错误地交换的调用。我尝试了什么:insertValues
.getName()
Table<Record4<String, String, Integer, Timestamp>> insertValues = values(
row( (String)null, (String)null, (Integer)null, (Timestamp)null )
).as("insert_values",
COMPANY.COMPANY_NAME.getName(),
PERSON.PERSON_NAME.getName(),
EMPLOYMENT_CONTRACT.SALARY.getName(),
EMPLOYMENT_CONTRACT.CREATION_DATE_TIME.getName()
);
这显然不起作用,jOOQ和Postgres都不知道插入的类型,DB猜测varchar并失败。我们需要 jOOQ 至少为查询中的第一行生成类型转换。再试一次:
Table<Record4<String, String, Integer, Timestamp>> insertValues = values(
row( COMPANY.COMPANY_NAME, PERSON.PERSON_NAME, EMPLOYMENT_CONTRACT.SALARY, EMPLOYMENT_CONTRACT.CREATION_DATE_TIME )
).as("insert_values");
这将是炸弹。JOOQ以这种方式知道正确的类型,并且可以为我生成强制转换,所有代码重复都消失了,一切都是安全的。但是,这也失败了。JOOQ不明白我给它一行满是空值。
有没有办法在没有不干净调用的情况下实现相同(或等效)的结果查询,直接将字段传递到某个地方?.getName()