While creating my application with Play Framework 2.3, I've spent lots of time for searching some things that seemed to be easy at first glance. One of such a thing was the use of PostgreSQL specific types: hstore and enums. I found a great library for that. Slick-pg provides good covers for the most of the PostgreSQL specific data types. However, I bumped into some problems using enums, so I provide here my example of using it (+ hstore + date). Hope, it'll be helpfull.
build.sbt (Add all necessary dependencies)
build.sbt (Add all necessary dependencies)
libraryDependencies ++= Seq( cache, ws, "org.postgresql" % "postgresql" % "9.3-1100-jdbc41", "com.typesafe.slick" %% "slick" % "2.1.0", "com.typesafe.play" %% "play-slick" % "0.8.0", "com.github.tminglei" %% "slick-pg" % "0.6.3" )
First of all you need to enable Hstore and create a enum type in your database.
CREATE EXTENSION IF NOT EXISTS hstore; CREATE TYPE pg_enum_type AS ENUM ('CREATED', 'JOINED', 'CLOSED');
app.utils.helpers.PostgresDriverPlus.scala (extend standart PostgreSQL driver with slick-pg)
package utils.helpers import com.github.tminglei.slickpg._ import slick.driver.PostgresDriver import models.MyTableStatus trait WithPostgresDriver { val driver: PostgresDriverPlus } trait PostgresDriverPlus extends PostgresDriver with PgHStoreSupport with PgEnumSupport with PgDateSupport{ override lazy val Implicit = new ImplicitsPlus {} override val simple = new SimpleQLPlus {} trait EnumImplicits { implicit val myTableStatusTypeMapper = createEnumJdbcType("pg_enum_type", MyTableStatus ) implicit val myTableStatusTypeListMapper = createEnumListJdbcType("pg_enum_type", MyTableStatus ) implicit val myTableStatusExtensionMethodsBuilder = createEnumColumnExtensionMethodsBuilder(MyTableStatus) } trait ImplicitsPlus extends Implicits with HStoreImplicits with DateTimeImplicits with EnumImplicits trait SimpleQLPlus extends SimpleQL with ImplicitsPlus } object PostgresDriverPlus extends PostgresDriverPlus
app.models.MyTable.scala (all type mappers are here)
package models import play.api.Play.current import play.api.db.slick.{ DB, Session } import utils.helpers.PostgresDriverPlus.simple._ import java.sql.{Timestamp, Date} import scala.Enumeration object MyTableStatus extends Enumeration { type MyTableStatus = Value val CREATED = Value("CREATED") val JOINED = Value("JOINED") val CLOSED = Value("CLOSED") } case class MyTable(id: Option[Int], date_start: Timestamp, status: MyTableStatus.MyTableStatus, date_finish: Date, spec: Map[String, String]) class MyTables(tag: Tag) extends Table[MyTable](tag, "mytable") /*Don't forget to be "mytable" in small letters!!! */ { def id = column[Int]("id", O.PrimaryKey, O.AutoInc) def date_start = column[Timestamp]("date_start", O.NotNull) def status = column[MyTableStatus.MyTableStatus]("status", O.NotNull) def date_finish = column[Date]("date_finish", O.NotNull) def spec = column[Map[String, String]]("spec", O.NotNull) //hstore is mapped to Map[String, String] def * = (id.?, date_start, status, date_finish, spec) <> (MyTable.tupled, MyTable.unapply) } object MyTables extends TableQuery(new MyTables(_)) { def findById(id: Int): Option[MyTable] = { DB withSession { implicit session: Session => MyTables.filter(_.id === id).firstOption } } def all = { DB withSession { implicit session: Session => MyTables.run } } def create(myTable: MyTable) = { DB withSession { implicit session: Session => MyTables.insert(myTable) } } }
So now you can use your model, for example, to insert data. You can run the following with "test-only InsertTestData" command.
test.InsertTestData.scala
import org.specs2.mutable.Specification import org.specs2.runner._ import org.junit.runner._ import play.api.test._ import play.api.test.Helpers._ import play.api.Play.current import models._ import scala.collection.immutable.HashMap @RunWith(classOf[JUnitRunner]) class InsertTestData extends Specification { "MyTables insert" should { "insert test data if MyTable model is empty" in { running(FakeApplication()) { if (MyTables.all.isEmpty) { import java.sql.Timestamp import java.text.SimpleDateFormat val sdf = new SimpleDateFormat("dd-M-yyyy") val joinBefore = "17-12-2014" val dateExpiry = "31-12-2014" MyTables.create(MyTable(None, new Timestamp((new java.util.Date).getTime()), MyTableStatus.CREATED, new java.sql.Date(sdf.parse(dateExpiry).getTime()), HashMap("type" -> "SuperType", "bla" -> "alb", "qwerty" -> "asdf") )) } MyTables.all must not be empty } } } }
0 коммент.:
Отправить комментарий