BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Slick 3: Reactive Streams for Asynchronous Database Access in Scala

Slick 3: Reactive Streams for Asynchronous Database Access in Scala

This item in japanese

Lire ce contenu en français

Slick, Typesafe's database query and access library for Scala, received a major overhaul in the just released version 3.0. Also dubbed "Reactive Slick", it introduces a new API to compose and run database queries in a reactive way. Reactive meaning that it supports the Reactive Streams API, an "initiative to provide a standard for asynchronous stream processing with non-blocking back pressure" (other implementations include Akka, MongoDB, RxJava, Vert.x, etc.) and supports building applications according to the Reactive Manifesto.

Database queries in Slick can be written as if they were operating on Scala collections, supporting the same vocabulary and similar operations (even though this illusion fails on more complex expressions). As a bonus, because the queries are not just plain strings, they are being type-checked by the compiler. An example of a simple join of two tables and a where-clause:

val q2 = for {
  c <- coffees if c.price < 9.0
  s <- suppliers if s.id === c.supID
} yield (c.name, s.name)

An equivalent SQL code could look like this:

select c.COF_NAME, s.SUP_NAME from COFFEES c, SUPPLIERS s where c.PRICE < 9.0 and s.SUP_ID = c.SUP_ID;

While the query API has remained largely unchanged in Slick 3, a query now returns a DBIOAction instead of an actual result (the old APIs are deprecated and will be removed in 3.1). Such actions can then be combined and in the end are passed to the database, where they will eventually be run. Here's an example of such a Slick 3 style query:

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") }

compared with the previous API:

val q = for (c <- coffees) yield c.name
val result = db.withSession {
  implicit session =>
  val s = q.list // <- takes session implicitly
  println(s"Result: $s")
}

The main benefit of the new approach is that it's completely asynchronous, so running a database-query won't block the calling thread. Also, results from the database can now be streamed. In combination with, for example, the Play Framework that supports Reactive Streams, this then frees up your request handling thread as quickly as possible.

InfoQ talked to Slick Tech-Lead Stefan Zeiger to learn more about the new release and their plans for the future.

InfoQ: The new API seems to mostly affect how queries are run, have there been any changes to how queries are constructed?

There are no fundamental changes to the way you write queries but there a two big new features: Outer joins are now correctly typed, returning an Option for one side (or both in case of a full outer join). This makes outer joins with mapped data types or over more than two tables straight-forward to write, where you previously had to perform some non-obvious and non-trivial mapping yourself in every query. The other big feature is the tsql interpolator that allows static verification and type inference for embedded SQL statements. Instead of waiting until runtime to discover errors in manually written SQL, the Scala compiler can now let the database perform the checks at compile-time.

InfoQ: Do you have any plans to create a Java API for Slick that makes use of Java 8's new Streams and lambdas, similar to Play or Akka's Java APIs?

Yes, this is something we would like to do in the near future in order to complete our full-stack solution for Java developers.

InfoQ: Does streaming and the new IO-API work will all databases or are there limitations?

The DBIO API is implemented on top of JDBC and works with all existing drivers. We are also looking into improved native support for databases with existing asynchronous drivers.

InfoQ: Can you share your plans for Slick 3.1 or 4.0?

The major feature currently in the works for Slick 3.1 is an improved query compiler back-end which generates simpler SQL code. This will make the generated code more readable for all users and should also provide some performance benefits, especially on MySQL where joins, as they are currently generated by Slick, often cannot use an index. As part of our commercial offering in the Reactive Platform we will add monitoring features specifically for Slick.

For the full list of changes, see the release announcement and don't forget to check the upgrade guide. To learn more about Slick 3, watch this ScalaDays talk by Stefan Zeiger.

Rate this Article

Adoption
Style

BT