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

如何使用Slick更新PostgreSQL的JSONB列?编译失败问题求解

如何用Slick更新PostgreSQL的JSONB列

你遇到的问题很典型——Slick原生并没有对PostgreSQL JSONB类型提供开箱即用的支持,所以直接像更新Integer列那样操作会编译失败。下面我会一步步给你解决方法,推荐用最常用的slick-pg扩展来处理JSONB,它能帮我们实现类型安全的JSONB操作。

第一步:添加slick-pg依赖

首先需要在你的构建文件(比如build.sbt)里添加slick-pg的依赖,确保版本和你用的Slick、PostgreSQL驱动版本匹配:

libraryDependencies ++= Seq(
  "com.github.tminglei" %% "slick-pg" % "0.20.6", // 版本请对应你的Slick版本
  "com.github.tminglei" %% "slick-pg_json4s" % "0.20.6", // 如果用json4s处理JSON
  // 若使用circe,可替换为slick-pg_circe
  "org.postgresql" % "postgresql" % "42.6.0",
  "com.typesafe.slick" %% "slick" % "3.4.1"
)

第二步:定义JSONB类型映射和表结构

接下来需要创建自定义的PostgreSQL配置,混入PgJsonSupport特质,让Slick能识别JSONB类型。同时,你需要把Scala里的JSON载体(比如case类、Map[String, Any]或json4s的JValue)和数据库的JSONB类型做映射。

举个例子,假设你的param.attrs是一个Map[String, Any]:

import slick.jdbc.PostgresProfile
import com.github.tminglei.slickpg._

// 自定义PostgreSQL Profile,添加JSONB支持
trait MyPostgresProfile extends PostgresProfile
  with PgJsonSupport {
  override val api = MyAPI

  object MyAPI extends API with JsonImplicits
}

object MyPostgresProfile extends MyPostgresProfile

// 导入自定义的Profile API
import MyPostgresProfile.api._

// 定义实体类
case class Device(sn: String, attrs: Map[String, Any])

// 定义表映射
class DevicesTable(tag: Tag) extends Table[Device](tag, "devices") {
  def sn = column[String]("sn", O.PrimaryKey)
  def attrs = column[Map[String, Any]]("attrs", O.SqlType("JSONB")) // 指定SQL类型为JSONB
  def * = (sn, attrs) <> (Device.tupled, Device.unapply)
}

val devices = TableQuery[DevicesTable]

如果你的attrs对应自定义case类,只需在自定义Profile中混入对应的序列化支持特质(比如PgJson4sSupport),并为case类定义JSON格式即可。

第三步:执行更新操作

现在你就可以用类似原来的方式更新JSONB列了,类型转换会由slick-pg自动处理:

// 假设param是包含sn和attrs的对象
val updateAction = devices
  .filter(_.sn === param.sn)
  .map(_.attrs)
  .update(param.attrs)

// 通过你的DB连接执行操作
db.run(updateAction)

备选方案:不用slick-pg,直接写原生SQL

如果暂时不想引入slick-pg,也可以用Slick的原生SQL操作更新JSONB列,不过这种方式没有类型安全保障:

import slick.jdbc.SQLActionBuilder

val updateSql = sqlu"""
  UPDATE devices 
  SET attrs = ${param.attrs}::jsonb 
  WHERE sn = ${param.sn}
"""

db.run(updateSql)

这里需要确保param.attrs能被正确序列化为JSON字符串,PostgreSQL会自动将其转换为JSONB类型。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:31:41