Reputation: 1071
Usually you would run two or more statements in a transaction. But in all the examples I could find on using transactionally
in Slick 3, there's a for comprehension to group these statements, when I usually use the for
in a loop.
This works (deleting from two tables in a transaction):
val action = db.run((for {
_ <- table1.filter(_.id1 === id).delete
_ <- table2.filter(_.id2=== id).delete
} yield ()).transactionally)
val result = Await.result(action, Duration.Inf)
But is the for/yield
needed? is there an alternative way just to run two or more statements in a transaction?
Upvotes: 2
Views: 7015
Reputation: 4471
You can use transactionally
on every DBIOAction
, not just those that are a result of the for comprehension. For example you can use transactionally
in combination with the DBIO.seq
method, which takes a sequence of actions and runs them sequentially:
val firstAction = table1.filter(_.id === id1).delete
val secondAction = table2.filter(_.id === id2).delete
val combinedAction = DBIO.seq(
firstAction,
secondAction
).transactionally
Upvotes: 9
Reputation: 2804
For your case for/yield
is not the only way to get what you need. But you will have to substitute it for the equivalent representation.
The for comprehension is syntactic sugar for a combination of flatMap
s and a map
. We need to use them because we are using monadic composition to aggregate all the actions in a BDIOAction
.
So you could also write it as:
val action = db.run(
table1.filter(_.id1 === id).delete.map ( _ =>
table2.filter(_.id2=== id).delete
).transactionally
)
val result = Await.result(action, Duration.Inf)
The for comprehension is usually used because is more clean, easier to understand and very easy to scale.
Lets have a look at an example with 4 statements in a transactions to see how it looks:
This would be with a for comprehension:
val action = db.run((for {
_ <- table1.filter(_.id1 === id).delete
_ <- table2.filter(_.id2=== id).delete
_ <- table3.filter(_.id3=== id).delete
_ <- table4.filter(_.id4=== id).delete
} yield ()).transactionally)
val result = Await.result(action, Duration.Inf)
This would be with flatMap/map
s:
val action = db.run(
table1.filter(_.id1 === id).delete.flatMap ( _ =>
table2.filter(_.id2 === id).delete.flatMap ( _ =>
table3.filter(_.id3 === id).delete.map ( _ =>
table4.filter(_.id4=== id).delete
)
)
).transactionally
)
val result = Await.result(action, Duration.Inf)
Upvotes: 7