我在理解新的Slick DBIOActionAPI时遇到了困难,文档中似乎没有太多的示例.我使用的是Slick 3.0.0,我需要执行一些DB操作,还需要对从数据库接收的数据进行一些计算,但所有这些操作都必须在单个事务中完成.我试着做以下几件事:

  1. 执行对数据库(types表)的查询.
  2. 对查询结果进行聚合和过滤(此计算无法在数据库上完成).
  3. 根据步骤2中的计算执行另一个查询(messages表-由于某些限制,此查询必须使用原始SQL).
  4. 将步骤2和步骤3中的数据连接到内存中.

我希望第1步和第3步中的查询在事务内部执行,因为它们的结果集中的数据必须是一致的.

我试着用一元连接的方式来做这件事.下面是我的代码的一个过于简化的版本,但我甚至无法编译它:

  val compositeAction = (for {
    rawTypes <- TableQuery[DBType].result
    (projectId, types) <- rawTypes.groupBy(_.projectId).toSeq.map(group => (group._1, group._2.slice(0, 10)))
    counts <- DBIO.sequence(types.map(aType => sql"""select count(*) from messages where type_id = ${aType.id}""".as[Int]))
  } yield (projectId, types.zip(counts))).transactionally
  1. for理解的第一行从types表中 Select 数据.
  2. 理解for的第二行应该对结果进行分组和切片,结果是Seq[(Option[String], Seq[String])]
  3. 理解for的第三行必须对上一步中的每个元素执行一组查询,具体而言,它必须对Seq[String]内的每个值执行单个SQL查询.所以在第三行,我构建了一个DBIOAction的序列.
  4. yieldzips第二步为types,第三步为counts.

但是,此构造不起作用,并产生两个编译时错误:

Error:(129, 16) type mismatch;
 found   : slick.dbio.DBIOAction[(Option[String], Seq[(com.centreit.proto.repiso.storage.db.models.DBType#TableElementType, Vector[Int])]),slick.dbio.NoStream,slick.dbio.Effect]
    (which expands to)  slick.dbio.DBIOAction[(Option[String], Seq[(com.centreit.proto.repiso.storage.db.models.TypeModel, Vector[Int])]),slick.dbio.NoStream,slick.dbio.Effect]
 required: scala.collection.GenTraversableOnce[?]
        counts <- DBIO.sequence(types.map(aType => sql"""select count(*) from messages where type_id = ${aType.id}""".as[Int]))
               ^
Error:(128, 28) type mismatch;
 found   : Seq[Nothing]
 required: slick.dbio.DBIOAction[?,?,?]
        (projectId, types) <- rawTypes.groupBy(_.projectId).toSeq.map(group => (group._1, group._2.slice(0, 10)))
                           ^

我try 使用DBIO.successful将第二行包装在DBIOAction中,它应该将一个常量值提升到DBIOAction一元:

(projectId, types) <- DBIO.successful(rawTypes.groupBy(_.projectId).toSeq.map(group => (group._1, group._2.slice(0, 10))))

但是在这段代码中,types变量被推断为Any,因此代码无法编译.

推荐答案

这样试一试:

val compositeAction = (for {
  rawTypes <- TableQuery[DBType].result
  pair <- DBIO.sequence(rawTypes.groupBy(_.projectId).toSeq.map(group => DBIO.successful(group)))
  counts <- DBIO.sequence(pair.head._2.map(aType => sql"""select count(*) from messages where type_id = ${aType.id}""".as[Int]))
} yield (pair.head._1, pair.head._2.zip(counts))).transactionally

Database相关问答推荐

用于在 Excel 中的两个列表之间进行筛选的辅助列

任何用于存储过程的静态代码分析工具?

安装 SQL Server Management Studio Express后提示:Cannot open user default database. Login failed.

在 SQL Server 中以编程方式创建数据库

Sql更新查询

使用 Mongoose 删除索引的推荐方法是什么?

SQL 历史(history)表设计

Android - SQLite 数据库存储在哪里?

是否可以在ORDER BY子句之后放置任何可能造成安全风险的内容?

用于 Java 桌面应用程序的最佳数据库是什么

MySQL 错误 - #1062 - Duplicate entry ' ' for key 2

寻找示例数据库设计的好方法

MySQL:LAST_INSERT_ID() 返回 0

一个表可以有两个外键吗?

PostgreSQL 唯一索引和字符串大小写

在数据库中存储业务逻辑

如何删除除了postgres中的少数数据库之外的所有数据库

有哪些不同类型的索引,每种索引的好处是什么?

在两列之间 Select 最近的日期

使用命令行在 Mysql 中导入压缩文件