Non riesco a comprendere la nuova API Slick DBIOAction
, che non sembra avere molti esempi nei documenti. Sto usando Slick 3.0.0, e ho bisogno di eseguire alcune azioni DB e anche alcuni calcoli con i dati ricevuti dal database, ma tutte queste azioni devono essere fatte all'interno di una singola transazione. Sto cercando di eseguire quanto segue:Esecuzione di azioni non di database in una transazione in Slick 3
- Eseguire una query sul database (la tabella
types
). - Effettua alcune aggregazioni e il filtraggio dei risultati della query (questo calcolo non può essere eseguito sul database).
- Esegui un'altra query, in base ai calcoli del passaggio 2 (la tabella
messages
- a causa di alcune limitazioni, questa query deve essere in SQL raw). - Unire i dati dei passaggi 2 e 3 nella memoria.
Desidero che le query dei passaggi 1 e 3 siano eseguite all'interno di una transazione, in quanto i dati delle serie di risultati devono essere coerenti.
Ho provato a farlo in uno stile di join monadico. Ecco una versione eccessivamente semplificata del mio codice, ma non riesco nemmeno a farlo per compilare:
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
- La prima fila di
for
comprensione seleziona i dati dalla tabellatypes
. - Si suppone che la seconda fila di
for
comprensione fare qualche raggruppamento e tranciatura dei risultati, con un conseguenteSeq[(Option[String], Seq[String])]
- La terza fila di
for
comprensione deve eseguire una serie di query per ogni elemento dal passaggio precedente, in In particolare, deve eseguire una singola query SQL per ciascuno dei valori all'interno diSeq[String]
. Quindi nella terza riga costruisco una sequenza diDBIOAction
s. yield
clausolazip
stypes
dal secondo passaggio ecounts
dal terzo passaggio.
Questa costruzione, tuttavia, non funziona e dà due errori in fase di compilazione:
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)))
^
Ho cercato di avvolgere la seconda linea in un DBIOAction
utilizzando DBIO.successful
, che dovrebbe alzare un valore costante nel DBIOAction
monad:
(projectId, types) <- DBIO.successful(rawTypes.groupBy(_.projectId).toSeq.map(group => (group._1, group._2.slice(0, 10))))
Ma in questo codice viene dedotta la variabile types
sia Any
, e il codice fa non compilare per questo.
Date un'occhiata a [questo esempio] (https://github.com/slick/slick/issues/1093#issuecomment-110252046) e vedere se ti aiuta –
@FelipeAlmeida Grazie, ma non è proprio quello di cui ho bisogno. In questo esempio, tutte le comprensioni sono aggiornamenti/eliminazioni/inserimenti, e non sono interconnessi dai loro risultati e non producono nulla (tutte le parti di sinistra sono '_').Nel mio caso, una delle mie azioni non ha nulla a che fare con il database e tutte le azioni restituiscono risultati che sono utilizzati in altre interpretazioni o nel 'rendimento'. –