如何使用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
相关产品推荐
相关产品推荐

