Introduction
What is Slick?
Slick (“Scala Language-Integrated Connection Kit”) is Lightbend’s Functional Relational Mapping (FRM) library for Scala that makes it easy to work with relational databases. It allows you to work with stored data almost as if you were using Scala collections while at the same time giving you full control over when database access happens and which data is transferred. You can also use SQL directly. Execution of database actions is done asynchronously, and Slick provides API facades for Cats Effect/FS2, Scala Future/Reactive Streams, and ZIO/ZStream.
sourceval limit = 10.0
// Your query could look like this:
( for( c <- coffees; if c.price < limit ) yield c.name ).result
// Equivalent SQL: select COF_NAME from COFFEES where PRICE < 10.0
When using Scala instead of raw SQL for your queries you benefit from compile-time safety and compositionality. Slick can generate queries for different back-end databases including your own, using its extensible query compiler.
See here for an overview of the supported database systems for which Slick can generate code.
Why Slick?
Slick gives you a middle path between writing raw SQL strings everywhere and using a classic ORM:
- Type-safe, composable queries built with normal Scala expressions.
- Explicit execution model: query construction and query execution are separate.
- Asynchronous execution with materialized (
run) and streaming (stream) modes. - Direct SQL support when writing SQL manually is the right tool.
sourceclass Coffees(tag: Tag) extends Table[(String, Double)](tag, "COFFEES") {
def name = column[String]("COF_NAME", O.PrimaryKey)
def price = column[Double]("PRICE")
def * = (name, price)
}
val coffees = TableQuery[Coffees]
source// Query that only returns the "name" column
// Equivalent SQL: select NAME from COFFEES
coffees.map(_.name)
// Query that limits results by price < 10.0
// Equivalent SQL: select * from COFFEES where PRICE < 10.0
coffees.filter(_.price < 10.0)
The same type safety applies to mistakes that would otherwise become runtime SQL errors:
source// The result of "select PRICE from COFFEES" is a Seq of Double
// because of the type safe column definitions
val coffeeNames: IO[Seq[Double]] = db.run(
)
// Query builders are type safe:
coffees.filter(_.price < 10.0)
// Using a string in the filter would result in a compilation error
And queries stay composable as your codebase grows:
source// Create a query for coffee names with a price less than 10, sorted by name
coffees.filter(_.price < 10.0).sortBy(_.name).map(_.name)
// The generated SQL is equivalent to:
// select name from COFFEES where PRICE < 10.0 order by NAME
Effectful Applications
Slick is built for asynchronous, non-blocking application designs.
Slick provides three API facades depending on your effect system:
- Cats Effect / FS2 (
slick.cats.Database) in the coreslickmodule - Scala Future / Reactive Streams (
slick.future.Database) inslick-future - ZIO / ZStream (
slick.zio.Database) inslick-zio
All three provide the same core operations:
db.run(action)for materialized resultsdb.stream(action)for streaming results
See Database for database configuration, dependencies, lifecycle management, and complete examples for all three facades.
Plain SQL Support
The Scala-based query API for Slick allows you to write database queries like queries for Scala collections. Please see Getting Started for an introduction. Most of this user manual focuses on this API.
If you want to write your own SQL statements and still execute them asynchronously like normal Slick queries, you can use the Plain SQL API:
sourceval limit = 10.0
sql"select COF_NAME from COFFEES where PRICE < $limit".as[String]
// Automatically using a bind variable to be safe from SQL injection:
// select COF_NAME from COFFEES where PRICE < ?
License
Slick is released under a BSD-Style free and open source software license.
Next Steps
- If you are new to Slick, continue to Getting Started
- For database setup and lifecycle management, see Database
- If you are migrating from Slick 3, read the Migrating to Slick 4 guide
- If you have used an ORM before, see Coming from ORM to Slick
- If you are familiar with SQL, see Coming from SQL to Slick