Databases
Interpolated values become prepared-statement parameters (SQL-injection safe).
43.1 Doobie (JDBC, Cats Effect)
Interpolated values become prepared-statement parameters (SQL-injection safe). check queries against the schema in tests.
import doobie.*, doobie.implicits.*, cats.effect.IO
val xa = Transactor.fromDriverManager[IO](
driver = "org.postgresql.Driver", url = "jdbc:postgresql:world", user = "postgres", password = "pw", logHandler = None)
case class Country(code: String, name: String, population: Long)
def bigCountries(min: Long): IO[List[Country]] =
sql"SELECT code, name, population FROM country WHERE population > $min"
.query[Country].to[List].transact(xa)
def insert(c: Country): ConnectionIO[Int] =
sql"INSERT INTO country (code, name, population) VALUES (${c.code}, ${c.name}, ${c.population})".update.run43.2 Skunk (pure Postgres protocol, no JDBC)
val q: Query[String, String] = sql"SELECT name FROM country WHERE code = $varchar".query(varchar)
session.prepare(q).flatMap(_.unique("NOR"))43.3 Slick (Lightbend) — functional relational mapping
class Users(tag: Tag) extends Table[(Int, String)](tag, "users"):
def id = column[Int]("id", O.PrimaryKey)
def name = column[String]("name")
def * = (id, name)
val users = TableQuery[Users]
db.run(users.filter(_.name like "A%").result)43.4 Quill, Magnum, ScalikeJDBC
Quill / ProtoQuill — compile-time generated SQL from Scala collection-like queries.
Magnum — simple, fast, Scala 3-first JDBC library.
ScalikeJDBC — SQL-centric, mature.
NoSQL: ReactiveMongo, mongo-scala-driver, phantom (Cassandra), redis4cats, elastic4s.
43.5 Migrations
Flyway or Liquibase (Java libraries), invoked at startup or via sbt plugins.