By Alvin Alexander. Last updated: November 1, 2024
In case these two examples disappear from the ZIO JDBC repository, I have made a copy of them here.
(I say that because earlier this week (late October, 2024) I was told the the ZIO JDBC library is no longer maintained, and then I was also told that they just found a new maintainer.)
That being said, here are the ZIO-JDBC examples. This first one is called Basic.scala
:
package zio.jdbc.examples
import zio._
import zio.jdbc._
object Basic {
val age = 42
val ex0: SqlFragment = sql"create table if not exists users(name varchar(255), age int)"
// Creating SQL statements using interpolation:
val ex1: SqlFragment = sql"select * from users where age = $age"
// Selecting into tuples:
val ex2: Query[(String, Int)] = sql"select name, age from users".query[(String, Int)]
// Inserting from tuples:
val ex3: SqlFragment = sql"insert into users (name, age)".values(("John", 42))
// Inserting from case class
val ex4: SqlFragment = sql"insert into users (name, age)".values(User("John", 42))
// dropping table
val ex5: SqlFragment = sql"drop table if exists users"
// Composing requests:
val keyColumn = "key"
val valueColumn = "value"
def ex4(offset: Long): Query[(String, String)] =
(s"select $keyColumn, $valueColumn from events" ++ sql"where id > $offset").query[(String, String)]
// Executing statements:
val res1: ZIO[ZConnectionPool, Throwable, Option[(String, Int)]] =
transaction {
sql"select name, age from users where name = 'Sherlock Holmes'".query[(String, Int)].selectOne
}
}
And this one is called App.scala
:
import zio._
import zio.jdbc._
import zio.schema.{ Schema, TypeId }
/**
* You'll need the appropriate JDBC driver, and a database running.
*/
object App extends ZIOAppDefault {
import zio.jdbc.examples.User._
val create: ZIO[ZConnectionPool, Throwable, Unit] = transaction {
Basic.ex0.execute
}
val insertRow: ZIO[ZConnectionPool, Throwable, UpdateResult[Long]] = transaction {
sql"insert into users (name, age)".values(sampleUser1, sampleUser2).insertWithKeys
}
val select: ZIO[ZConnectionPool, Throwable, Chunk[User]] = transaction {
Basic.ex2.as[User].selectAll
}
val drop: ZIO[ZConnectionPool, Throwable, Unit] = transaction {
Basic.ex5.execute
}
val zioPoolConfig: ULayer[ZConnectionPoolConfig] =
ZLayer.succeed(ZConnectionPoolConfig.default)
val properties: Map[String, String] = Map(
"user" -> "postgres",
"password" -> "postgres"
)
/**
* Pre defined ZConnection Pools exist for:
* Postgres, SQL Server, Oracle, MySQL and h2
* custom pools, can also be constructed
*/
val connectionPool: ZLayer[ZConnectionPoolConfig, Throwable, ZConnectionPool] =
ZConnectionPool.postgres("localhost", 5432, "postgres", properties)
val program: ZIO[ZConnectionPool, Throwable, Chunk[User]] = for {
_ <- create *> insertRow
res <- select
_ <- drop
} yield res
override def run: ZIO[Scope with ZIOAppArgs, Any, Any] =
for {
results <- program.provideLayer(zioPoolConfig >>> connectionPool)
_ <- Console.printLine(results.mkString("\n"))
} yield ()
}
final case class User(name: String, age: Int)
object User {
import Schema.Field
implicit val schema: Schema[User] =
Schema.CaseClass2[String, Int, User](
TypeId.parse(classOf[User].getName),
Field("name", Schema[String], get0 = _.name, set0 = (x, v) => x.copy(name = v)),
Field("age", Schema[Int], get0 = _.age, set0 = (x, v) => x.copy(age = v)),
User.apply
)
// One can derive a jdbc codec from a zio-schema or
implicit val jdbcDecoder: JdbcDecoder[User] = JdbcDecoder.fromSchema
implicit val jdbcEncoder: JdbcEncoder[User] = JdbcEncoder.fromSchema
val sampleUser1: User = User("John", 42)
val sampleUser2: User = User("Sandra", 27)
// a custom decoder from a tuple
// implicit val jdbcDecoder = JdbcDecoder[(String, Int)].map[User](t => User(t._1, t._2))
}
These ZIO JDBC examples show how to do many SQL things with the library, including:
- SQL
select
statements - SQL
drop
statements - SQL
insert
statements - Connection pools/pooling
- Connect to a database with ZIO JDBC
- Transactions
- ZIO JDBC
Schema
This does not show SQL update
and delete
examples, but I have some of those around here ... er ... somewhere. I’ll post them when I find them.