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
Slick 3 Transactions
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
Slick is a Functional Relational Mapping library for Scala that allows us to query and access a database like other Scala collections. We can write database queries in Scala instead of SQL, thus providing typesafe queries.
Slick is the most popular library for database access in the Scala ecosystem. Slick provides compile-time safety and composability to our queries. By default, it also encourages an asynchronous and non-blocking style of programming. Also, it follows the Reactive Stream based streaming APIs.
We can also write plain SQL queries and execute them similarly to any other Slick queries. Slick supports most of the popular databases like PostgreSQL, MySQL, Oracle, MS SQL Server, etc. 3. Dependencies
Slick allows us to compose and execute multiple actions. For instance, if we need to insert a new player and delete an existing player, we can combine both the operations into a single action: The action combinedAction can now be executed using db.run () method. 6.6. Executing Queries in a Transaction
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With