Integrating Play 2.1 with Slick 1.0.0 Database Query DSL
Join the DZone community and get the full member experience.
Join For FreeFor people in hurry here is the code and the steps to setup.
Refer this blog on Play 2.0: Building Web Application using Scala for details on Play and Scala.
In the next few blogs I will be writing enterprise class web application using Play and Scala. I will be covering topics like Database modelling and Security. Now officially Scala has adopted Slick as the Database query DSL. But when you create a new Play application and add Slick library as mentioned in this blog, it is not working. It gives a strange error like No suitable driver found in tests.
I also found slick-play2-example, this sample expect us to create a DAL layer, but we cannot directly play with slick in our test code.
After much further research I came across this plugin. I tried integrating this with my Play application and it worked like a charm.
We will define a Coffee class and a Supplier class. One Coffee has multiple Suppliers. The class design is as below,
case class Coffee(name: String, supID: Int, price: Double, sales: Int, total: Int) object Coffees extends Table[Coffee]("COFFEES") { def name = column[String]("COF_NAME", O.PrimaryKey) def supID = column[Int]("SUP_ID") def price = column[Double]("PRICE") def sales = column[Int]("SALES") def total = column[Int]("TOTAL") def * = name ~ supID ~ price ~ sales ~ total <> (Coffee.apply _, Coffee.unapply _) // A reified foreign key relation that can be navigated to create a join def supplier = foreignKey("SUP_FK", supID, Suppliers)(_.id) } case class Supplier(id: Int, name: String, street: String, city: String, state: String, zip: String) // Definition of the SUPPLIERS table object Suppliers extends Table[Supplier]("SUPPLIERS") { def id = column[Int]("SUP_ID", O.PrimaryKey) // This is the primary key column def name = column[String]("SUP_NAME") def street = column[String]("STREET") def city = column[String]("CITY") def state = column[String]("STATE") def zip = column[String]("<a class="zem_slink" title="ZIP (file format)" href="http://en.wikipedia.org/wiki/ZIP_%28file_format%29" target="_blank" rel="wikipedia">ZIP</a>") // Every table needs a * projection with the same type as the table's type parameter def * = id ~ name ~ street ~ city ~ state ~ zip <> (Supplier.apply _, Supplier.unapply _) }
Below is the ScalaTest to test various capabilities of Slick,
DB.withSession{ implicit session => //Populate sample data val testSuppliers = Seq( Supplier(101, "Acme, Inc.", "99 Market Street", "Groundsville", "CA", "95199"), Supplier( 49, "Superior Coffee", "1 Party Place", "Mendocino", "CA", "95460"), Supplier(150, "The High Ground", "100 Coffee Lane", "Meadows", "CA", "93966") ) Suppliers.insertAll( testSuppliers: _*) val testCoffees= Seq( Coffee("Colombian", 101, 7.99, 0, 0), Coffee("French_Roast", 49, 8.99, 0, 0), Coffee("Espresso", 150, 9.99, 0, 0), Coffee("Colombian_Decaf", 101, 8.99, 0, 0), Coffee("French_Roast_Decaf", 49, 9.99, 0, 0) ) Coffees.insertAll( testCoffees: _*) //Assert coffee data equals to the test list of coffee Query(Coffees).list must equalTo(testCoffees) //List all coffee less than $10 val q1 = for { c <- Coffees if c.price < 10.0 } yield (c.name) q1 foreach println println("**************"); //return all suppliers for coffee less than $9.0 val q2 = for { c <- Coffees if c.price < 9.0 s <- c.supplier } yield (c.name, s.name) q2 foreach println println("**************"); //return all suppliers for coffee using zip val q3 = for { (c, s) <- Coffees zip Suppliers } yield (c.name, s.name) q3 foreach println println("**************"); //Union val q4 = Query(Coffees).filter(_.price < 8.0) val q5 = Query(Coffees).filter(_.price > 9.0) val unionQuery = q4 union q5 unionQuery foreach println println("**************"); //Union second approach val unionAllQuery = q4 unionAll q5 unionAllQuery foreach println println("**************"); //Group by val r = (for { c <- Coffees s <- c.supplier } yield (c, s)).groupBy(_._1.supID) //Aggregation val r1 = r.map { case (supID, css) => (supID, css.length, css.map(_._1.price).avg) } r1 foreach println }
In my next blog, I will take a real example and implement using Slick. I hope this blog helped.
Published at DZone with permission of Krishna Prasad, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments