簡體   English   中英

在Slick 3中的事務中執行非數據庫操作

[英]Executing non-database actions in a transaction in Slick 3

我無法理解新的Slick DBIOAction API,它似乎在文檔中沒有很多示例。 我正在使用Slick 3.0.0,我需要執行一些數據庫操作以及從數據庫接收的數據的一些計算,但所有這些操作都必須在單個事務中完成。 我正在嘗試執行以下操作:

  1. 對數據庫執行查詢( types表)。
  2. 對查詢結果進行一些聚合和過濾(無法在數據庫上進行此計算)。
  3. 根據步驟2中的計算執行另一個查詢( messages表 - 由於某些限制,此查詢必須在原始SQL中)。
  4. 將步驟2和3中的數據加入內存中。

我希望步驟1和3中的查詢在事務內執行,因為結果集中的數據必須一致。

我試圖用monadic join樣式做到這一點。 這是我的代碼的過度簡化版本,但我甚至無法編譯:

  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表。
  2. 的第二行for理解應該做的結果的一些分組和切片,從而產生Seq[(Option[String], Seq[String])]
  3. 理解的第三行必須for上一步中的每個元素執行一組查詢,特別是,它必須為Seq[String]每個值執行單個SQL查詢。 所以在第三行中我構建了一系列DBIOAction
  4. yield子句zip小號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)))
                           ^

我試圖通過使用DBIO.successful來包裝DBIOAction的第二行,這應該將一個常量值提升到DBIOAction monad中:

(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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM