Doobie查询返回Option[A]时报错找不到Read实例如何解决?
Doobie无法构造Option[A]的Read实例问题解决
错误根因
Doobie 提供的默认Read实例仅支持字段级别的Option映射(即行中某一列可为空时映射为Option[字段类型]),没有直接提供整行维度的Option[A]类型的Read实例。你当前直接将查询结果的行映射类型声明为Option[A],触发了隐式实例找不到的报错。
正确修改方案
你不需要手动定义Option[A]的Read实例,Doobie已经在查询执行层提供了对应能力,只需做两处调整:
- 修改
find方法的定义,将行映射类型改回A(你已经声明了A: Read的上下文绑定,该类型的隐式实例存在),同时补充ClassTag上下文绑定,否则你通过classTag获取运行时类的逻辑会报错。调整后的代码如下:
import scala.reflect.ClassTag abstract class CRUDAbs[A: Read : ClassTag](val tableName: String) extends TransactSQL { def table: Fragment = Fragment.const(s"$tableName") def columnsList: Array[String] = { val cls = classTag[A].runtimeClass cls.getDeclaredFields.map(_.getName).map(snakeCase) } def columns: Fragment = Fragment.const(columnsList.mkString(",")) // 行映射类型改为A,返回Query0[A] def find(id: Int): doobie.Query0[A] = (sql"select " ++ columns ++ sql" from " ++ table ++ sql" where " ++ Fragment.const( s"${columnsList.head}" ) ++ sql" = $id").query[A] }
- 执行查询时调用
.option方法获取Option[A]类型的结果
该方法是Doobie专门为「最多返回1行的查询」提供的语义封装:如果查询没有匹配行返回None,有匹配行返回Some(映射后的A实例),使用示例如下:
// xa为你初始化的Transactor实例 val result: IO[Option[A]] = find(1).option.transact(xa)
内容的提问来源于stack exchange,提问作者Миша Попов
相关产品推荐
相关产品推荐

