import java.sql.Connection
case class Book(title: String)
val getBooks: Connection => List[Book] =
{ c =>
val q = "SELECT TITLE FROM BOOK"
val stmt = c.createStatement
val rs = stmt.executeQuery(q)
def _books(acc: List[Book]): List[Book] =
if (rs.next()) {
_books(Book(rs.getString("TITLE")) :: acc)
} else {
.close
stmt
acc}
_books(Nil)
}
val initDb: Connection => Unit =
{ c =>
val s = "CREATE TABLE IF NOT EXISTS BOOK(TITLE VARCHAR(256) NOT NULL)"
val stmt = c.createStatement
.executeUpdate(s)
stmt.close
stmt}
def addBook(b: Book): Connection => Unit =
{ c =>
val s = "INSERT INTO BOOK (TITLE) VALUES (?)"
val stmt = c.prepareStatement(s)
.setString(1, b.title)
stmt.executeUpdate
stmt.close
stmt}
implicit class Queries[A](val g: Connection => A) {
def map[B](f: A => B): Connection => B =
{ c => f(g(c)) }
def flatMap[B](f: A => Connection => B): Connection => B =
{ c => f(g(c)).g(c) }
}
val booksQ =
for {
<- initDb
_ <- addBook(Book("Surely You're Joking, Mr. Feynman!"))
_ <- getBooks
books } yield books
Class.forName("org.h2.Driver")
val c = java.sql.DriverManager.getConnection("jdbc:h2:mem:testdb", "sa", "")
val books = booksQ(c)
.close
c
println(s"Books: ${books}") // Books: List(Book(Surely You're Joking, Mr. Feynman!))
This file is literate Scala, and can be run using Codedown:
/***
+= "com.h2database" % "h2" % "1.4.178"
libraryDependencies */
$ curl https://earldouglas.com/posts/scala/jdbc.md |
codedown scala > scala-jdbc.scala
$ sbt -Dsbt.main.class=sbt.ScriptMain scala-jdbc.scala
Books: List(Book(Surely You're Joking, Mr. Feynman!))