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

Scala Akka+PostgreSQL+Doobie类型不匹配:找到Seq,需String

问题分析与解决

核心错误原因

  1. 类型不匹配直接诱因:你在dbGetTerrain里试图把查询返回的Seq[Terrain]直接传给Terrain的构造函数,但Terrain需要的是id: String, parent: String, waterPercentage: Double, landPercentage: Double四个独立参数,而非集合类型,这就导致了编译器提示“Found: Seq[Terrain], Required: String”的错误。
  2. 数据类型映射不一致:数据库表Terrain_registry的id字段是INT类型,但你定义的Terrain case class里id是String类型,Doobie无法自动完成这种类型转换,后续即使解决了前面的类型错误,也会出现查询映射失败的问题。
  3. 函数返回值与实际结果不匹配:函数声明返回单个Terrain,但你的SQL查询是获取所有parent匹配的行,实际返回的是多个结果(Seq[Terrain]),这本身就存在逻辑矛盾。

修复步骤

1. 修正Case Class的类型映射

把Terrain的id类型改成和数据库一致的Int:

final case class Terrain(id: Int, parent: String, waterPercentage: Double, landPercentage: Double)

2. 根据需求调整函数实现

场景1:获取所有匹配parent的地形(返回多个结果)

修改函数返回类型为Seq[Terrain],去掉错误的Terrain构造调用:

def dbGetTerrain(xa: Transactor, parentId: String): Seq[Terrain] = {
  sql"SELECT id, parent, waterPercentage, landPercentage FROM Terrain_registry WHERE parent = $parentId"
    .query[Terrain]
    .to[Seq]
    .transact(xa)
    .unsafeRunSync()
}

场景2:获取单个匹配的地形(如确保parent唯一,或取第一个结果)

如果业务上只需要单个结果,用option方法返回Option[Terrain]:

def dbGetTerrain(xa: Transactor, parentId: String): Option[Terrain] = {
  sql"SELECT id, parent, waterPercentage, landPercentage FROM Terrain_registry WHERE parent = $parentId"
    .query[Terrain]
    .option
    .transact(xa)
    .unsafeRunSync()
}

场景3:Akka异步推荐写法(避免阻塞)

在Akka应用中,不建议使用unsafeRunSync()阻塞线程,应该返回IO类型让上层处理异步流程:

def dbGetTerrain(xa: Transactor, parentId: String): IO[Seq[Terrain]] = {
  sql"SELECT id, parent, waterPercentage, landPercentage FROM Terrain_registry WHERE parent = $parentId"
    .query[Terrain]
    .to[Seq]
    .transact(xa)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:49:55