I have a question about Slick 3 and Transactions
I have read the documentation
http://slick.typesafe.com/doc/3.1.0/dbio.html
and the other Slick 3 transaction questions
Executing non-database actions in a transaction in Slick 3
But they didn't help me
I need to read some values from the database, run some logic in Scala, and then depending on the result, modify the database. I want the entire operation to be atomic.
My code looks something like this:
database.run(TableQuery[X].filter(blah).result).map { x =>
database.run {
if( someLogicNotInSQL(x) )
TableQuery[Y].insert(someFoo)
else
TableQuery[Y].insert(someBah)
}
}
How do I get the value of the query, run some logic in Scala, and then run another action (e.g. insert) all as one atomic transaction.
Thanks Peter
To run this in a transaction you will want to construct a single action that contains your queries and logic. Then run that action with a transaction.
Modifying your example:
import scala.concurrent.ExecutionContext.Implicits.global
val action =
tableQuery.filter(blah).result.flatMap { x =>
if (someLogicNotInSql(x))
tableQuery.insert(someFoo)
else
tableQuery.insert(someBah)
}
flatMap
requires as an argument a function from x
to a DBIO[T]
. It will sequence the two action together, allowing the second to use the result of the first.
To run this combined action you''ll need a execution context. (Because your computation, if (someLogicNotInSql ...
, will have to run on some thread somewhere, not Slick's internal execution context).
You can wrap this combined action in a transaction and just call run
once:
val future = database.run(action.transactionally)