You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ZIO-Quill 条件更新实现:如何按用户值更新表行?

仅更新Scala样例类中非None字段的数据库实现

假设使用Slick(Scala主流数据库访问库),以下是实现动态更新的完整方案:

1. 定义样例类与表映射

首先是你的Person样例类,以及对应的Slick表映射:

case class Person(id: Long, firstName: Option[String], age: Option[Int], email: Option[String], address: Option[String])

import slick.jdbc.H2Profile.api._

class Persons(tag: Tag) extends Table[Person](tag, "PERSONS") {
  def id = column[Long]("ID", O.PrimaryKey)
  def firstName = column[Option[String]]("FIRST_NAME")
  def age = column[Option[Int]]("AGE")
  def email = column[Option[String]]("EMAIL")
  def address = column[Option[String]]("ADDRESS")

  override def * = (id, firstName, age, email, address) <> (Person.tupled, Person.unapply)
}

val persons = TableQuery[Persons]

2. 动态构建更新方法

核心逻辑是筛选出传入对象中所有非None的字段,仅将这些字段加入更新语句:

def updatePerson(person: Person): DBIO[Int] = {
  // 收集需更新的列与对应值,过滤掉None项
  val updatePairs = Seq(
    person.firstName.map(persons.map(_.firstName) -> _),
    person.age.map(persons.map(_.age) -> _),
    person.email.map(persons.map(_.email) -> _),
    person.address.map(persons.map(_.address) -> _)
  ).flatten

  if (updatePairs.isEmpty) {
    // 无字段需更新,直接返回0行更新结果
    DBIO.successful(0)
  } else {
    // 动态生成更新语句,仅包含非空字段
    val updateQuery = persons
      .filter(_.id === person.id)
      .map(_ => updatePairs.map(_._1))
      .update(updatePairs.map(_._2))
    updateQuery
  }
}

3. 使用示例

对于你提供的person1对象,调用方法后只会更新address字段:

val person1 = Person(1, None, None, None, Some("33, xyz st"))

// 执行更新(需提前配置数据库连接)
val db = Database.forConfig("your-db-config")
try {
  val updatedRows = db.run(updatePerson(person1)).await
  println(s"成功更新 $updatedRows 行")
} finally db.close()

其他ORM(以Quill为例)

如果使用Quill,核心思路一致,动态拼接更新表达式:

import io.getquill._

val ctx = new SqlMirrorContext(PostgresDialect, SnakeCase)
import ctx._

def updatePersonQuill(person: Person): Unit = {
  val updateFields = List(
    person.firstName.map(f => _.firstName -> lift(f)),
    person.age.map(a => _.age -> lift(a)),
    person.email.map(e => _.email -> lift(e)),
    person.address.map(addr => _.address -> lift(addr))
  ).flatten

  if (updateFields.nonEmpty) {
    val updateQuery = quote {
      query[Person]
        .filter(_.id == lift(person.id))
        .update(updateFields: _*)
    }
    ctx.run(updateQuery)
  }
}

核心逻辑总结

无论使用哪种数据库访问库,关键都是只将传入对象中Some类型的字段纳入更新范围,避免用None覆盖数据库中已存在的有效值,实现精准的条件更新。

内容的提问来源于stack exchange,提问作者Jimmy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 14:32:55