database scala slick slick-3.0

database - Ejecutar acciones que no son de base de datos en una transacción en Slick 3



scala slick-3.0 (1)

Inténtalo de esta manera:

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

Estoy teniendo problemas para entender la nueva API Slick DBIOAction , que no parece tener muchos ejemplos en la documentación. Estoy utilizando Slick 3.0.0, y necesito ejecutar algunas acciones de la base de datos y también algunos cálculos con los datos recibidos de la base de datos, pero todas esas acciones deben realizarse dentro de una sola transacción. Estoy tratando de hacer lo siguiente:

  1. Ejecutar una consulta a la base de datos (la tabla de types ).
  2. Realice algunas agregaciones y filtre los resultados de la consulta (este cálculo no se puede realizar en la base de datos).
  3. Ejecute otra consulta, según los cálculos del paso 2 (la tabla de messages , debido a algunas limitaciones, esta consulta debe estar en SQL sin formato).
  4. Unir los datos de los pasos 2 y 3 en la memoria.

Quiero que las consultas de los pasos 1 y 3 se ejecuten dentro de una transacción, ya que los datos de sus conjuntos de resultados deben ser coherentes.

He tratado de hacer esto en un estilo de unión monádica. Aquí hay una versión muy simplificada de mi código, pero ni siquiera puedo compilarlo:

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. La primera fila de for comprensión selecciona los datos de la tabla de types .
  2. Se supone que la segunda fila de for comprensión hace un poco de agrupación y corte de los resultados, dando como resultado un Seq[(Option[String], Seq[String])]
  3. La tercera fila de for comprensión tiene que ejecutar un conjunto de consultas para cada elemento del paso anterior, en particular, tiene que ejecutar una única consulta SQL para cada uno de los valores dentro de Seq[String] . Así que en la tercera fila construyo una secuencia de DBIOAction s.
  4. La cláusula de yield zip los types s desde el segundo paso y counts desde el tercer paso.

Esta construcción, sin embargo, no funciona y da dos errores de tiempo de compilación:

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))) ^

He intentado envolver la segunda línea en una DBIOAction utilizando DBIO.successful , que se supone eleva un valor constante en la mónada DBIOAction :

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

Pero en este código se infiere que la variable de types es Any , y el código no se compila debido a eso.