underscoreio / slickless

Support for shapeless HLists/Generics in Slick.
Apache License 2.0
163 stars 22 forks source link
scala shapeless slick

slickless

Build Status codecov Join the chat at https://gitter.im/underscoreio/slickless

Shapeless HList support for Slick.

by Richard Dallaway, Miles Sabin, and Dave Gurnell.

Copyright 2015-2019 Underscore Consulting LLP. Licensed Apache 2.

Versions

Scala Slick Slickless
2.13 3.3 Maven Central
2.12 3.3 Maven Central
2.12 3.2 0.3.3
2.11 3.1 0.3.0

Getting Started

Grab the code by adding the following to your build.sbt:

libraryDependencies ++= Seq(
  "com.typesafe.slick" %% "slick"     % "3.3.2",
  "com.chuusai"        %% "shapeless" % "2.3.3",
  "io.underscore"      %% "slickless" % "<<VERSION>>"
)

Synopsis

Import Slick, shapeless, and slickless, and you should be able to define Tables on any shapeless HList type:

import slick.jdbc.H2Profile.api._
import shapeless.{ HList, ::, HNil }
import slickless._

class Users(tag: Tag) extends Table[Long :: String :: HNil](tag, "users") {
  def id    = column[Long]( "id", O.PrimaryKey, O.AutoInc )
  def email = column[String]("email")

  def * = id :: email :: HNil
}

lazy val users = TableQuery[Users]

If you want to map your HList to a case class (i.e. you have a case class that has more than 22 fields and you are using slickless to bypass this limit), you can do the following

import slick.jdbc.H2Profile.api._
import shapeless.{ HList, ::, HNil, Generic }
import slickless._

case class User(id: Long, email: String)

class Users(tag: Tag) extends Table[User](tag, "users") {
  def id    = column[Long]( "id", O.PrimaryKey, O.AutoInc )
  def email = column[String]("email")

  def * = (id :: email :: HNil).mappedWith(Generic[User])
}

lazy val users = TableQuery[Users]

Notes

Compile time

Due to this issue, if you accidentally make a mapping which is incorrect, the Scala compiler can take a huge amount of time to report an error. If your slickless project is taking an insanely long amount of time to compile (more than a couple of minutes), try to make sure you have the mapping correct before using <>.

Build example without default resolvers

If you need to add resolvers into your build, here's an example:

resolvers += "Maven Central" at "https://repo1.maven.org/maven2/"

resolvers += Resolver.sonatypeRepo("releases")

resolvers += Resolver.sonatypeRepo("snapshots")

libraryDependencies ++= Seq(
  "com.typesafe.slick" %% "slick"     % "3.2.1",
  "com.chuusai"        %% "shapeless" % "2.3.3",
  "io.underscore"      %% "slickless" % "0.3.3"
)

Publishing

We use the sbt-pgp plugin and the sbt-sonatype plugin to publish to Maven Central.

Publish sequence could be:

sbt> set pgpPassphrase := Some(Array('s','e','c','r','3','t'))
sbt> set publishTo := sonatypePublishTo.value
sbt> +publishSigned
sbt> sonatypeRelease