更新 ScalikeJDBC 中的返回查询

Update returning queries in ScalikeJDBC

范围为 implicit val session: DBSession,具体为 scalikejdbc.AutoSession:

更新工作

sql"""
    update payments set status=${status.name} where id in ($ids)
""".update().apply()

并选择作品

sql"""
   select id
   from payments
   where status='valid'
""".map(_.long).list().apply()

但是更新返回列失败,因为事务设置为只读。

sql"""
  update payments
  set status='submitted'
  where status='pending'
  and scheduled <= ${ZonedDateTime.now.toInstant}
  returning id
""".map(_.long).iterable().apply().toIterator

org.postgresql.util.PSQLException: ERROR: cannot execute UPDATE in a read-only transaction.

sessionSQLToResult 内匹配,假设它应该是只读的:

  case AutoSession | ReadOnlyAutoSession => DB.readOnly(f)

我曾尝试创建自己的 DBSession 以避免匹配这种模式,但放弃了这种方法。我最接近让它工作的是:

val writeableSession: DBSession = DBSession(session.connection, isReadOnly = false)

def inner()(implicit session: DBSession): Iterator[Payment] = {
  sql"""
  update payments
  set status='submitted'
  where status='pending'
  returning id
""".map(_.long).iterable().apply().toIterator
}

inner()(writeableSession)

这失败了,因为 session.connectionnull

如何将其强制为 localTx 而不是 readOnly?

一般来说,AutoSession 表现为 DDL 和 insert/update/delete 操作的自动提交会话,而它作为 select 查询的只读会话。

看来直接按照下面的方法做就好了

DB.localTx { implicit session =>
  // Have both the update operation and select query inside this block
}