2014-07-10 4 views
1

(Этот вопрос основан на очень похожий previous request for help. С введением в DAO и нескольких драйверов база данных, такая же проблема требует иного подхода, и я надеюсь, что гарантирует отсутствие нового SO вопрос.)Где разместить методы доступа к базе данных при использовании DAO с Slick 2.0?

У меня есть class и Slick Table определяется следующим образом:

import play.api.db.slick.Profile 

case class Foo(title: String, description: String, id: Int = 0) 

trait FooComponent extends Profile { this: Profile => 
    import profile.simple._ 

    class FooTable(tag: Tag) extends Table[Foo](tag, "FOO") { 

    def id = column[Int]("ID", O.PrimaryKey, O.AutoInc) 
    def title = column[String]("TITLE", O.NotNull) 
    def description = column[String]("DESCRIPTION") 

    def * = (title, description, id) <> (Foo.tupled, Foo.unapply) 
    } 
} 

и объект доступа к данным:

class DAO(override val profile: JdbcProfile) extends FooComponent with Profile { 
    val foos = TableQuery[FooTable] 
} 

object current { 
    val dao = new DAO(DB(play.api.Play.current).driver) 
} 

Это довольно удивительным, потому что теперь я могу добавить что-то вроде следующего в моей application.conf:

db.default.driver=org.h2.Driver 
db.default.url="jdbc:h2:mem:play" 

db.test.driver=org.postgresql.Driver 
db.test.user="testuser" 
db.test.password="" 
db.test.url="jdbc:postgresql:testdb" 

... и если я делаю следующее в контроллере:

import models.current.dao._ 
import models.current.dao.profile.simple._ 

У меня есть доступ к мой foosTableQuery, и он автоматически получает URL-адрес драйвера и базы данных для db.default в application.conf.

В такой же, но не совсем, как-хороший способ, я могу сделать следующее в моем тесте Specification:

"test Foos" in new WithApplication() { 
    val dao = new DAO(play.api.db.slick.DB("test").driver) 
    import dao._ //import all our database Tables 
    import dao.profile.simple._ //import specific database methods 

    play.api.db.slick.DB("test").withSession { implicit s: Session => 
    println(s.conn.getMetaData.getURL) 
    println(foos.list) 
    } 

Однако, что если я хочу, чтобы определить метод, который может действовать на TableQuery[Foo]? Что-то вроде этого:

def findByTitle(title: String) = foos.filter(_.id === id).list 

Проблема

Что такое правильный способ написания метода findByTitle, и где я должен поставить его так, что я могу:

  • Называйте это таким образом, чтобы он не сталкивался с методом с тем же именем, который действует на TableQuery[Bar]. Исходя из OO, я чувствую, что хочу сделать что-то вроде foos.findByTitle("someFoo"), но если есть лучший способ сделать этот функциональный стиль, я открыт для предложений.
  • Позвоните из приложения Контроллер, чтобы запрос работал с моим водителем h2 db.default, и из моего теста Specification, чтобы он работал с моим драйвером postgres db.test.

Как и в стороне, если я могу сделать это в моей DAO:

object current { 
    val dao = new DAO(DB(play.api.Play.current).driver) 
} 

, а затем import models.dao.current._ в любом месте я хочу использовать этот DAO, как я могу продлить ту же форму на следующее :

object test { 
    val dao = new DAO(play.api.db.slick.DB("test").driver) 
} 

Если я пытаюсь сделать это, компилятор жалуется, не имея an implicit Application in scope.

+0

Для кого-то, кто был смущен (как и я), о том, почему мой DAO не содержит «Таблицу» и имеет класс DAO (переопределить val-профиль: JdbcProfile), расширяет FooComponent с помощью Profile' вместо 'class DAO (val driver: JdbcProfile) ', как вы можете видеть в других примерах, я использую плагин play-slick. Проверьте различия между этими двумя примерами: [play-slick] (https://github.com/playframework/play-slick/blob/master/samples/play-slick-cake-sample/app/models/DAO.scala) и [slick] (https://github.com/slick/slick-examples/blob/master/src/main/scala/com/typesafe/slick/examples/lifted/MultiDBExample.scala) ... – sjwarner

ответ

1

Если вы используете плагин play slick, ему потребуется приложение для запуска игры, чтобы иметь возможность вызывать код, который использует доступ к БД из этого плагина, вы можете быть уверены, что запустите приложение для воспроизведения в своих тестах, используя WithApplication, как описано в docs: http://www.playframework.com/documentation/2.3.x/ScalaFunctionalTestingWithSpecs2

2

Я думаю, вам нужно прочитать в неявных преобразованиях и неявных параметрах в Scala. Доступны онлайн-книги Scala.

Когда вы получаете сообщение об ошибке в отсутствии неявного, это означает, что вы столкнулись с ошибкой проверки типов, предоставляемой библиотекой, которая препятствует вам делать что-то неправильно, но здесь это не так. Или вы просто забыли сделать доступным неявное. Существует два способа сделать доступным неявное. Либо импортируйте его в область получения сообщения об ошибке. Или в основном отложить поиск к callsite вашего метода. Не уверен, какой из них подходит для игры. Вам нужно либо импортировать неявное приложение из игры, либо вам нужно включить val dao в метод и запросить неявное приложение в списке неявных аргументов def dao(implicit app: Application) = .... Вы можете альтернативно повернуть тест в класс и запросить его там.