Scala Akka+PostgreSQL+Doobie类型不匹配:找到Seq,需String
问题分析与解决
核心错误原因
- 类型不匹配直接诱因:你在
dbGetTerrain里试图把查询返回的Seq[Terrain]直接传给Terrain的构造函数,但Terrain需要的是id: String, parent: String, waterPercentage: Double, landPercentage: Double四个独立参数,而非集合类型,这就导致了编译器提示“Found: Seq[Terrain], Required: String”的错误。 - 数据类型映射不一致:数据库表
Terrain_registry的id字段是INT类型,但你定义的Terraincase class里id是String类型,Doobie无法自动完成这种类型转换,后续即使解决了前面的类型错误,也会出现查询映射失败的问题。 - 函数返回值与实际结果不匹配:函数声明返回单个
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
相关产品推荐
相关产品推荐

