Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slick 3 Transactions with logic in Scala

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

like image 402
opus111 Avatar asked Oct 26 '15 18:10

opus111


People also ask

What is slick in Scala?

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.

What is the best database library for Scala?

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.

Does slick support plain SQL queries?

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

How to combine and execute multiple actions in slick?

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


1 Answers

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)
like image 155
Richard Dallaway Avatar answered Sep 24 '22 04:09

Richard Dallaway