Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get values from query result in slick

I tried to use the Slick(3.0.2) to operate database in my project with scala. Here is my part of code

val query = table.filter(_.username === "LeoAshin").map { user => (user.username, user.password, user.role, user.delFlg) }

val f = db.run(query.result)

How can I read the data from "f" I have tried google the solution many times, but no answer can solved my confuse Thanks a lot

like image 477
LeoAshin Avatar asked Dec 28 '16 12:12

LeoAshin


2 Answers

f is a Future and there are several things you can do to get at the value, depending on just how urgently you need it. If there's nothing else you can do while you're waiting then you will just have to wait for it to complete and then get the value. Perhaps the easiest is along the following lines (from the Slick documentation):

val q = for (c <- coffees) yield c.name
val a = q.result
val f: Future[Seq[String]] = db.run(a)
f.onSuccess { case s => println(s"Result: $s") }

You could then go on to do other things that don't depend on the result of f and the result of the query will be printed on the console asynchronously.

However, most of the time you'll want to use the value for some other operation, perhaps another database query. In that case, the easiest thing to do is to use a for comprehension. Something like the following:

for (r <- f) yield db.run(q(r))

where q is a function/method that will take the result of your first query and build another one. The result of this for comprehension will also be a Future, of course.

One thing to be aware of is that if you are running this in a program that will do an exit after all the code has been run, you will need to use Await (see the Scala API) to prevent the program exiting while one of your db queries is still working.

like image 173
Phasmid Avatar answered Nov 01 '22 11:11

Phasmid


Type of query.result is DBIO. When you call db.run, it turns into Future.

If you want to print the data, use

import scala.concurrent.ExecutionContext.Implicits.global
f.foreach(println)

To continue working with data, use f.map { case (username, password, role, delFlg) ⇒ ... }

If you want to block on the Future and get the result (if you're playing around in REPL for example), use something like

import scala.concurrent.Await
import scala.concurrent.duration._
Await.result(f, 1.second)

Bear in mind, this is not what you want to do in production code — blocking on Futures is a bad practice.

I generally recommend learning about Scala core types and Futures specifically. Slick "responsibility" ends when you call db.run.

like image 28
Anna Zubenko Avatar answered Nov 01 '22 11:11

Anna Zubenko