jooq、postgres 和从多个表更新和返回数据失败
jooq, postgres and update and returning data from multible tables fails
在更新其中一个 table 中的字段时,我很难制定一个 jooq 查询来对来自两个 table 的 return 数据进行查询。 (Postgres 9.6, jooq 3.11)
DEVICE 表和 CUSTOMER 表是根据外键约束连接的
DEVICE.CUSTOMERID = CUSTOMER.ID.
我想 return 一个符合条件的 device.id 和设备客户的 customer.secret 并将 device.state 更新为 IN_PROGRESS。资格由各种条款评估。
我从
开始
final Record task = db
.update(DEVICE)
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.from(CUSTOMER)
.where(DEVICE.CUSTOMERID.eq(CUSTOMER.ID))
.and(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
这导致 ERROR: Field ("public"."customer"."secret") is not contained in Row
我基于此 建模了另一个查询,但最终出现了同样的错误。
final Record task = db
.update(DEVICE)
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.from(CUSTOMER, db
.select()
.from(CUSTOMER
.join(DEVICE).on(CUSTOMER.ID.eq(DEVICE.CUSTOMERID)))
.forUpdate()
)
.where(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
ERROR: Field ("public"."customer"."secret") is not contained in Row
我尝试了几种排列,但最终出现了一些错误变化
- table名称
"<customer/device>"
指定了不止一次
- 缺少 table
"<customer/device>"
的 FROM 子句条目
我有信心,可以进行这样的查询,但我 运行 没有想法。有什么建议吗?
我尝试过的代表性变体列表
final Record task = db
.update(DEVICE)
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.from(
DEVICE.join(CUSTOMER).on(DEVICE.CUSTOMERID.eq(CUSTOMER.ID)))
.where(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
ERROR: table name "device" specified more than once
final Record task = dbContext
.update(DEVICE.join(CUSTOMER).on(DEVICE.CUSTOMERID.eq(CUSTOMER.ID)))
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.where(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
ERROR: syntax error at or near "join"
final Record task = db
.update(DEVICE)
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.from(db.select().from(CUSTOMER,
DEVICE.join(CUSTOMER).on(DEVICE.CUSTOMERID.eq(CUSTOMER.ID))).forUpdate()
)
.where(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
ERROR: table name "customer" specified more than once
final Record task = db
.update(DEVICE)
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.from(db.select().from(
DEVICE.join(CUSTOMER).on(DEVICE.CUSTOMERID.eq(CUSTOMER.ID))).forUpdate()
)
.where(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
ERROR: missing FROM-clause entry for table "customer"
final Record task = db
.update(DEVICE)
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.from(CUSTOMER.join(DEVICE).on(CUSTOMER.ID.eq(DEVICE.CUSTOMERID)))
.where(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
ERROR: table name "device" specified more than once
这是因为 jOOQ API 中的旧设计错误,其中 returning()
clause 导致 return 类型 Result<R>
或 R
,而不是您正在获取的实际列。因此,您只能更新 table 中的 return 列,而不能更新任何其他 table 或任意表达式。由于向后兼容,这不能轻易改变。
但是,从 jOOQ 3.11 开始,您现在可以调用 returningResult()
as a workaround to get the exact row type you're specifying: https://github.com/jOOQ/jOOQ/issues/7475
在更新其中一个 table 中的字段时,我很难制定一个 jooq 查询来对来自两个 table 的 return 数据进行查询。 (Postgres 9.6, jooq 3.11)
DEVICE 表和 CUSTOMER 表是根据外键约束连接的 DEVICE.CUSTOMERID = CUSTOMER.ID.
我想 return 一个符合条件的 device.id 和设备客户的 customer.secret 并将 device.state 更新为 IN_PROGRESS。资格由各种条款评估。
我从
开始 final Record task = db
.update(DEVICE)
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.from(CUSTOMER)
.where(DEVICE.CUSTOMERID.eq(CUSTOMER.ID))
.and(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
这导致 ERROR: Field ("public"."customer"."secret") is not contained in Row
我基于此
final Record task = db
.update(DEVICE)
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.from(CUSTOMER, db
.select()
.from(CUSTOMER
.join(DEVICE).on(CUSTOMER.ID.eq(DEVICE.CUSTOMERID)))
.forUpdate()
)
.where(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
ERROR: Field ("public"."customer"."secret") is not contained in Row
我尝试了几种排列,但最终出现了一些错误变化
- table名称
"<customer/device>"
指定了不止一次 - 缺少 table
"<customer/device>"
的 FROM 子句条目
我有信心,可以进行这样的查询,但我 运行 没有想法。有什么建议吗?
我尝试过的代表性变体列表
final Record task = db
.update(DEVICE)
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.from(
DEVICE.join(CUSTOMER).on(DEVICE.CUSTOMERID.eq(CUSTOMER.ID)))
.where(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
ERROR: table name "device" specified more than once
final Record task = dbContext
.update(DEVICE.join(CUSTOMER).on(DEVICE.CUSTOMERID.eq(CUSTOMER.ID)))
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.where(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
ERROR: syntax error at or near "join"
final Record task = db
.update(DEVICE)
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.from(db.select().from(CUSTOMER,
DEVICE.join(CUSTOMER).on(DEVICE.CUSTOMERID.eq(CUSTOMER.ID))).forUpdate()
)
.where(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
ERROR: table name "customer" specified more than once
final Record task = db
.update(DEVICE)
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.from(db.select().from(
DEVICE.join(CUSTOMER).on(DEVICE.CUSTOMERID.eq(CUSTOMER.ID))).forUpdate()
)
.where(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
ERROR: missing FROM-clause entry for table "customer"
final Record task = db
.update(DEVICE)
.set(DEVICE.STATE, StateEnum.IN_PROGRESS)
.from(CUSTOMER.join(DEVICE).on(CUSTOMER.ID.eq(DEVICE.CUSTOMERID)))
.where(DEVICE.STATE.eq(StateEnum.NEW))
.and(CUSTOMER.SECRETCONFIRMED.eq(true))
.returning(DEVICE.ID, CUSTOMER.SECRET)
.fetchOne();
ERROR: table name "device" specified more than once
这是因为 jOOQ API 中的旧设计错误,其中 returning()
clause 导致 return 类型 Result<R>
或 R
,而不是您正在获取的实际列。因此,您只能更新 table 中的 return 列,而不能更新任何其他 table 或任意表达式。由于向后兼容,这不能轻易改变。
但是,从 jOOQ 3.11 开始,您现在可以调用 returningResult()
as a workaround to get the exact row type you're specifying: https://github.com/jOOQ/jOOQ/issues/7475