【问题标题】:Can Slick's insertOrUpdate modify a subset of columns in the event the record already exists?如果记录已经存在,Slick 的 insertOrUpdate 可以修改列的子集吗?
【发布时间】:2017-03-02 18:31:48
【问题描述】:

在我的用例中,我有一个 createdDate 字段,如果记录已经存在,我想保留它。

case class Record(id:Long, value:String, createdDate:DateTime, updateDate:DateTime)

是否可以使用 TableQuery.insertOrUpdate(record) 以便在记录已经存在的情况下只更新记录的一部分?

就我而言,我只想更改 value 和 updateDate 字段。在存储过程中使用纯 SQL,我会执行以下操作:

merge Record r
using (
    select @id,
           @value
) as source (
    id,
    value
)
on r.id = source.id
when matched then 
    update set value = source.value, updateDate = getDate()
when not matched then 
    insert (id, value, createdDate, updatedDate) values
    (id, value, getDate(), getDate()

【问题讨论】:

  • 你有没有找到解决这个问题的办法?我遇到了同样的问题,到目前为止我看到的唯一解决方法是不使用 insertOrUpdate 并切换到编写我自己的 upsert 逻辑。

标签: sql scala slick upsert


【解决方案1】:

Slick 的insertOrUpdate 可以修改列的子集吗?

不,我不相信 insertOrUpdate 函数可以做到这一点。这是requested as a feature,但目前尚未实现。

我们如何解决这个问题?

由于the update function does support updating a specific list of columns,我们可以编写自己的upsert逻辑,而不是使用insertOrUpdate函数。它可能会像这样工作:

def insertOrUpdate(record: Record): Future[Int] = {
  val insertOrUpdateAction = for {
    recordOpt <- records.filter(_.id === record.id).result.headOption
    updateAction = recordOpt.map(_ => updateRecord(record))
    action <- updateAction.getOrElse(insertRecord(record))
  } yield action
  connection.run(insertOrUpdateAction)
}

private def updateRecord(record: Record) = {
  val query = for {
    r <- records.filter(_.id === record.id)
  } yield (r.value, r.updatedDate) // list of columns which can be updated
  query.update(record.value, record.updatedDate)
}

private def insertRecord(record: Record) = records += record

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-29
    • 1970-01-01
    相关资源
    最近更新 更多