How to run a transactionally
statement in Slick 3.1.x, and capture the result in a Future (without the use of Await)?
This works (but uses Await)
val action = db.run((for {
_ <- table1.filter(_.id1 === id).delete
_ <- table2.filter(_.id2=== id).delete
} yield ()).transactionally)
val result = Await.result(action, Duration.Inf)
However this does not print anything:
val future = db.run((for {
_ <- table1.filter(_.id1 === id).delete
_ <- table2.filter(_.id2=== id).delete
} yield ()).transactionally)
future.map { result => println("result:"+result) }
UPDATE
This is the real code taken from the program that doesn't work. It prints "1" but it never prints "2"
case class UserRole (sk: Int, name: String)
class UserRoleDB(tag: Tag) extends Table[UserRole](tag, "user_roles") {
def sk = column[Int]("sk", O.PrimaryKey)
def name = column[String]("name")
def * = (sk, name) <> ((UserRole.apply _).tupled, UserRole.unapply)
}
class Test extends Controller {
def index = Action.async { request =>
val db = Database.forConfig("db1")
val userRoles = TableQuery[UserRoleDB]
val ur = UserRole(1002,"aaa")
try {
val action = (for {
userRole2 <- userRoles += ur
} yield (userRole2)).transactionally
val future = db.run(action)
println(1)
// val result = Await.result(future, Duration.Inf)
future.map { result => {
println(2)
Ok("Finished OK")
}
}
}
finally db.close
}
}
Coming from the other question you asked: You are opening and then immediately closing the db connection in the
finally
clause. Therefore your async db operation runs against a closed db connection. That's also why it works by usingAwait
since that blocks the execution ofdb.close
until you received the result set.So how to fix this?
Either you move
db.close
intofuture.map
or better you let play-slick handle db connections for you.Side note
You should close your other question and update this thread accordingly instead.
Your second example is fine. My guess is that you are either running it in standalone program or in test - and it simply finishes before future has a chance to be executed.
Try to add some sleep after your code in your second sample and you'll see it is getting printed. This is definitely not something (this sleep) you would do in your actual code but it will show you it works as it should.