tessl install tessl/maven-com-typesafe-slick--slick_2-12@2.1.0Scala Language-Integrated Connection Kit - A modern database query and access library for Scala that 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 a database access happens and which data is transferred.
Slick is a comprehensive database access library for Scala that provides a type-safe, functional programming approach to database interactions. It allows you to work with stored data almost as if you were using Scala collections while giving you full control over when a database access happens and which data is transferred.
libraryDependencies += "com.typesafe.slick" %% "slick" % "2.1.0"The most common import pattern is to import everything from a specific driver:
import scala.slick.driver.H2Driver.simple._
// This imports: Database, Session, Table, Query, Column, TableQuery, and all DSL operationsSpecific component imports:
// Core lifted embedding
import scala.slick.lifted.{Query, TableQuery, Column, AbstractTable}
// JDBC plain SQL support
import scala.slick.jdbc.{GetResult, SetParameter, StaticQuery}
// Schema modeling
import scala.slick.model.{Model, Table, Column => ModelColumn}
// Database backends
import scala.slick.jdbc.JdbcBackend.DatabaseHere's a simple example showing table definition and basic queries:
import scala.slick.driver.H2Driver.simple._
import scala.slick.jdbc.JdbcBackend.Database
// Table definition
class Users(tag: Tag) extends Table[(Int, String)](tag, "USERS") {
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def name = column[String]("NAME")
def * = (id, name)
}
val users = TableQuery[Users]
// Database operations
Database.forURL("jdbc:h2:mem:test1", driver="org.h2.Driver") withSession { implicit session =>
// Create table
users.ddl.create
// Insert data
users += (1, "John")
users += (2, "Jane")
// Query data
val query = users.filter(_.name === "John").map(_.id)
val result = query.list // List[Int]
// Type-safe queries
val allUsers = users.list // List[(Int, String)]
}Slick is built around several key architectural components:
Slick supports multiple database drivers with database-specific optimizations.
// Main database drivers
object H2Driver extends JdbcDriver
object MySQLDriver extends JdbcDriver
object PostgresDriver extends JdbcDriver
object SQLiteDriver extends JdbcDriver
object DerbyDriver extends JdbcDriver
object AccessDriver extends JdbcDriver
object HsqldbDriver extends JdbcDriver
// Usage pattern
import scala.slick.driver.H2Driver.simple._The main query DSL for type-safe database operations.
// Core query types
abstract class Query[+E, U, C[_]] extends QueryBase[C[U]] {
def map[F, G, T](f: E => F): Query[G, T, C]
def flatMap[F, T, D[_]](f: E => Query[F, T, D]): Query[F, T, C]
def filter[T <: Column[_]](f: E => T): Query[E, U, C]
def sortBy[T <% Ordered](f: E => T): Query[E, U, C]
def groupBy[K, T, G, P](f: E => K): Query[K, G, C]
def join[E2, U2, D[_]](q2: Query[E2, U2, D]): Query[(E, E2), (U, U2), C]
def take(num: Long): Query[E, U, C]
def drop(num: Long): Query[E, U, C]
}
class TableQuery[E <: AbstractTable[_]] extends Query[E, E#TableElementType, Seq]
// Factory methods
object TableQuery {
def apply[E](cons: Tag => E): TableQuery[E]
def apply[E]: TableQuery[E] = macro // Macro-based constructor
}Type-safe table schema definitions and constraints.
// Base table class
abstract class AbstractTable[T](val tableTag: Tag, val schemaName: Option[String], val tableName: String) {
def * : ProvenShape[T] // Required default projection
// Column definition
def column[C](n: String, options: ColumnOption[C]*): Column[C]
// Constraints
def primaryKey[T](name: String, sourceColumns: T): PrimaryKey
def foreignKey[P, PU, TT, U](name: String, sourceColumns: P, targetTable: TableQuery[TT]): ForeignKeyQuery[TT, U]
def index[T](name: String, on: T, unique: Boolean = false): Index
}
// Column operations
abstract class Column[T] extends Rep[T] {
def asc: ColumnOrdered[T]
def desc: ColumnOrdered[T]
def ===[P2, R](e: Column[P2]): Column[R]
def =!=[P2, R](e: Column[P2]): Column[R]
}
// Table instance marker
sealed trait TagLow-level JDBC access and plain SQL query support.
// Database backend
object JdbcBackend {
abstract class DatabaseDef {
def withSession[T](f: Session => T): T
def withTransaction[T](f: Session => T): T
}
trait Session {
def conn: java.sql.Connection
}
}
// Plain SQL queries
object StaticQuery {
def apply[R](query: String): StaticQuery[Unit, R]
}
// Result extraction
trait GetResult[T] {
def apply(rs: PositionedResult): T
}
// Parameter setting
trait SetParameter[T] {
def apply(v: T, pp: PositionedParameters): Unit
}
// SQL interpolation
implicit class SQLInterpolation(val sc: StringContext) {
def sql[T](params: Any*): StaticQuery[Unit, T]
def sqlu(params: Any*): StaticQuery[Unit, Int]
}Database capability abstraction and driver architecture.
// Profile hierarchy
trait BasicProfile {
type Backend <: DatabaseComponent
val simple: SimpleQL
val Implicit: Implicits
}
trait RelationalProfile extends BasicProfile {
type Table[T] <: AbstractTable[T]
type Sequence[T] <: BasicSequence[T]
type ColumnType[T] <: TypedType[T]
}
trait SqlProfile extends RelationalProfile
trait JdbcProfile extends SqlProfile {
type Backend = JdbcBackend
val backend: Backend = JdbcBackend
}
// Capability system
case class Capability(name: String)Runtime schema representation and reverse engineering.
// Complete schema model
case class Model(
tables: Seq[Table],
options: Set[ModelOption[_]] = Set.empty
)
// Table representation
case class Table(
name: QualifiedName,
columns: Seq[Column],
primaryKey: Option[PrimaryKey],
foreignKeys: Seq[ForeignKey] = Seq.empty,
indices: Seq[Index] = Seq.empty,
options: Set[TableOption[_]] = Set.empty
)
// Column representation
case class Column(
name: String,
table: QualifiedName,
tpe: String,
nullable: Boolean,
options: Set[ColumnOption[_]] = Set.empty
)
// Qualified naming
case class QualifiedName(
table: String,
schema: Option[String] = None,
catalog: Option[String] = None
)// Core representation types
trait Rep[T]
// Shape system for type mapping
abstract class Shape[Level, -Mixed_, Unpacked_, Packed_]
type ProvenShape[T] = Shape[FlatShapeLevel, T, T, Column[T]]
// Exception handling
class SlickException(msg: String) extends RuntimeException(msg)
// Query condition constraint
trait CanBeQueryCondition[-T] {
def apply(value: T): Column[Boolean]
}
// Column options
sealed trait ColumnOption[+T]
object ColumnOption {
case object PrimaryKey extends ColumnOption[Nothing]
case object AutoInc extends ColumnOption[Nothing]
case object NotNull extends ColumnOption[Nothing]
case class Default[T](defaultValue: T) extends ColumnOption[T]
}
// Convenient aliases
object O {
val PrimaryKey = ColumnOption.PrimaryKey
val AutoInc = ColumnOption.AutoInc
val NotNull = ColumnOption.NotNull
def Default[T](v: T) = ColumnOption.Default(v)
}