Skip to content

Instantly share code, notes, and snippets.

@siman
Created November 13, 2013 23:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save siman/7458258 to your computer and use it in GitHub Desktop.
Save siman/7458258 to your computer and use it in GitHub Desktop.
Postgres DAO with Slick (Scala)
package models
import scala.slick.driver.PostgresDriver.simple._
import Database.threadLocalSession
import scala.slick.jdbc.{GetResult, StaticQuery => Q}
trait AbstractDao[Id, E] {
def countAll: Int
def listAll: List[E]
def findById(id: Id): Option[E]
def deleteById(id: Id): Boolean
def saveOrUpdate(e: E): Option[E]
}
trait LongKeyAbstractDao[E] extends AbstractDao[Long, E]
case class Event(
id: Option[Long] = None,
title: String,
ticketsLeft: Int
)
abstract class AbstractTable[E](_tableName: String) extends Table[E](_tableName) {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
}
abstract class AbstractSlickDao[E](table: AbstractTable[E]) extends LongKeyAbstractDao[E] {
protected def idOf(e: E): Option[Long]
protected def copyWithId(e: E, newId: Option[Long]): E
protected def nextIdSql = "select nextval('" + table.tableName + "_id_seq')"
protected def nextId: Option[Long] = Q.queryNA[Long](nextIdSql).firstOption
def countAll: Int = (for {t <- table} yield t.id.countDistinct).firstOption.getOrElse(0)
def listAll: List[E] = (for {t <- table} yield t).list
protected def findByIdQuery(id: Long) = (for {t <- table if t.id === id} yield t)
def findById(id: Long): Option[E] = findByIdQuery(id).firstOption
def deleteById(id: Long): Boolean = findByIdQuery(id).delete > 0
def saveOrUpdate(e: E): Option[E] = {
(idOf(e) match {
case None => // Insert new
val eWithId = copyWithId(e, nextId)
(table.insert(eWithId), eWithId)
case Some(id) => // Update existent
(findByIdQuery(id).update(e), e)
}) match {
case (updRows, updE) if updRows > 0 => Some(updE)
case _ => None
}
}
}
object EventTable extends AbstractTable[Event]("event") {
def title = column[String]("title")
def ticketsLeft = column[Int]("tickets_left")
def * = id.? ~ title ~ ticketsLeft <> (Event.apply _, Event.unapply _)
}
trait EventDao extends LongKeyAbstractDao[Event]
class EventSlickDao extends AbstractSlickDao[Event](EventTable) {
protected def idOf(e: Event): Option[Long] = e.id
protected def copyWithId(e: Event, newId: Option[Long]): Event = e.copy(id = newId)
}
object AppContext {
val EventDao = new EventSlickDao
def doInSession[R](f: => R): R = {
// TODO: Use tomcat pool.
// Move to props.
Database.forURL(
"jdbc:postgresql://localhost:5432/tickes",
driver = "org.postgresql.Driver",
user = "postgres",
password = "qwerty"
) withTransaction(f)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment