Slick 3中DBIO Tuple结果编译错误及查询执行方法求助
Slick 3 解决键值表查询与关联表过滤的编译问题
问题场景
你需要实现这样的逻辑:从键值表中获取指定key的值,不存在则插入默认值并返回;再用这个值作为条件查询另一张带自增主键的表,最终返回过滤后的结果和这个值。你在Slick 2里的写法可以正常运行,但迁移到Slick 3后出现了编译错误。
错误原因
Slick 3彻底转向了异步的DBIOAction模型,不再支持Slick 2里直接同步获取结果的方式。你的代码中vLogTable.filter(_.id > last).take(limit).result返回的是一个StreamingProfileAction(属于DBIOAction的子类),而不是直接的Seq[VLogEntry],所以无法直接赋值给rds,这就是编译报错的核心原因。
修正后的代码
def lastLogs(limit: Long = 666): Future[(Long, Seq[VLogEntry])] = { val q: DBIO[(Long, Seq[VLogEntry])] = for { existing <- kvTable.filter(_.key === "log").result.headOption conf = existing getOrElse KV(key = "log", value = "0") last = conf.value.toLong // 用<-来获取DBIOAction的结果,而不是直接赋值 rds <- vLogTable.filter(_.id > last).take(limit).result // 执行插入或更新操作,这里即使conf是已存在的,insertOrUpdate也会做更新(如果值有变化) _ <- kvTable.insertOrUpdate(conf) } yield { (last, rds) } db.run(q) }
关键说明
- DBIO上下文的异步处理:在Slick 3的
for推导式中,每一个<-都对应一个DBIOAction的执行,会自动处理异步流程,你不需要手动调用result或list来触发查询——db.run会统一执行整个DBIO流程并返回Future。 - insertOrUpdate的作用:当
existing不存在时,conf是我们创建的默认KV对象,insertOrUpdate会执行插入;如果existing存在,它会对比现有数据,有变化则更新,无变化则不操作,正好符合你的需求。 - 类型匹配:修正后的代码中,
rds会被正确推导为Seq[VLogEntry],因为<-会提取出DBIOAction的最终结果值,解决了编译时的类型不匹配问题。
内容的提问来源于stack exchange,提问作者Rin malavi
相关产品推荐
相关产品推荐

