Scala 3项目中Quill使用List[Int]时的解码器警告消除求助
Scala 3项目中Quill使用List[Int]时的解码器警告消除求助
我完全懂你这种“代码能跑但警告甩不掉”的烦躁感!咱们先把这个Quill的警告问题掰明白,再彻底解决掉它。
问题a:为啥List[Int]没被自动正确处理?
首先得说Quill的类型检查逻辑——它对所有在查询里用到的类型,都要求同时有编码器(Encoder)和解码器(Decoder),哪怕你当前写的是UPDATE语句(本来不需要返回数据)。
你用到的List[Int],Quill默认给你提供了编码器(不然你的参数根本传不进SQL),但对应的解码器却没自动绑定上。这不是List[Int]本身的问题,而是Quill针对不同数据库的默认配置差异:比如有些数据库的数组类型和Scala List的映射,解码器需要显式声明,Quill不会自动帮你生成。
问题b:怎么添加合适的List[Int]解码器消警告?
解决方法分两种,取决于你用的数据库:
情况1:用PostgreSQL(最常见的场景)
PostgreSQL原生支持数组类型,Quill的Postgres上下文里其实有现成的arrayIntDecoder,你只需要把它转换成List[Int]的解码器就行。可以在你的上下文定义里显式声明:
import io.getquill._ import io.getquill.context.jdbc.PostgresJdbcContext // 假设你的Quill上下文是这样的 object MyDbContext extends PostgresJdbcContext(SnakeCase, "your-db-config-name") { // 把数组解码器转换成List[Int]解码器 implicit val listIntDecoder: Decoder[List[Int]] = arrayIntDecoder.map(_.toList) // 如果编码器也需要显式声明的话(其实默认有,但加上更保险) implicit val listIntEncoder: Encoder[List[Int]] = arrayIntEncoder.contramap(_.toArray) }
然后在使用查询的地方导入这个上下文的所有成员:
import MyDbContext._ // 你的原有代码不变 val rawQuery = quote { (id: Int, crs: List[Int]) => sql"""UPDATE caze SET results=results || $crs WHERE id=$id""" .as[Update[Caze]] } val numberOfUpdates = run(rawQuery(lift(caseId), lift(caseResultIds)))
情况2:用其他数据库(比如MySQL)
MySQL的数组类型支持比较特殊(通常用字符串模拟),这时候你需要自定义解码器:
implicit val listIntDecoder: Decoder[List[Int]] = Decoder { (index, row, session) => val arrayStr = row.getString(index) // 假设数据库里存的是类似"[1,2,3]"的字符串,解析成List[Int] arrayStr.stripPrefix("[").stripSuffix("]").split(",").map(_.trim.toInt).toList } // 编码器也要对应自定义(如果之前没的话) implicit val listIntEncoder: Encoder[List[Int]] = Encoder { (index, value, session) => val arrayStr = value.mkString("[", ",", "]") session.preparedStatement.setString(index, arrayStr) }
把这两个隐式值放在你的Quill上下文或者使用查询的作用域里,Quill就能找到它们,警告自然就消失了。
额外说明
Quill的这个警告是预防性的——它怕你之后把查询改成SELECT(比如需要返回包含List[Int]的结果),到时没有解码器就会直接报错,所以提前提醒你补全。现在补完解码器,不仅警告没了,后续扩展查询也更安全。
备注:内容来源于stack exchange,提问作者nondeterministic
相关产品推荐
相关产品推荐

