Статьи

Интеграция Play 2.1 с Slick 1.0.0 Database Query DSL

Для спешащих людей приведен код и инструкции по настройке .

Обратитесь к этому блогу в  Play 2.0: Создание веб-приложения с использованием Scala для получения подробной информации о Play и Scala.

В следующих нескольких блогах я буду писать веб-приложение корпоративного класса с использованием Play и Scala. Я буду освещать такие темы, как моделирование баз данных и безопасность. Теперь официально Scala приняла Slick в качестве DSL для запросов к базе данных . Но когда вы создаете новое приложение Play и добавляете библиотеку Slick, как упоминалось в этом блоге , оно не работает. Это выдает странную ошибку, такую ​​как Не найдено подходящего драйвера в тестах.

Я также нашел slick-play2-example , в этом примере ожидается, что мы создадим слой DAL, но мы не можем напрямую поиграть со slick в нашем тестовом коде.

После долгих исследований я наткнулся на этот плагин . Я попытался интегрировать это с моим приложением Play, и это сработало как шарм.

Мы определим класс Кофе и класс Поставщика. Один кофе имеет несколько поставщиков. Дизайн класса, как показано ниже,

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 _)
}

Ниже ScalaTest для тестирования различных возможностей 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
}

В моем следующем блоге я приведу реальный пример и буду использовать Slick. Я надеюсь, что этот блог помог.