在使用带有Slick 2.0的DAO时,在哪里放置我的数据库访问方法?

时间:2014-07-10 06:14:51

标签: scala slick slick-2.0 play-slick

(这个问题是基于一个非常相似的previous request for help。随着DAO和多个数据库驱动程序的引入,同样的问题需要采用不同的方法,我希望保证一个新的SO问题。)

我有一个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._

我可以访问foos TableQuery,并自动获取db.defaultapplication.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")这样的事情,但如果有更好的方式来做这种功能风格,我可以接受建议。
  • 从应用程序控制器调用它,以便查询将与我的db.default h2驱动程序以及我的测试Specification一起使用,以便它可以与我的db.test postgres驱动程序一起使用。< / LI>

顺便说一句,如果我可以把它放在我的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

2 个答案:

答案 0 :(得分:2)

我认为您需要阅读Scala中的隐式转换和隐式参数。有在线Scala书籍。

当您收到有关缺失隐式的错误消息时,或者意味着您遇到了由库提供的失败类型检查,这会阻止您做错事,但事实并非如此。或者你只是忘了隐含可用。有两种方法可以使隐式可用。将其导入到您收到错误消息的范围。或者基本上将查找推迟到您方法的调用点。不确定哪一个是正确的游戏。您需要从play中导入隐式Application,或者需要将val dao转换为方法并在隐式参数列表def dao(implicit app: Application) = ...中请求隐式应用程序。您也可以将测试变成一个类并在那里请求它。

答案 1 :(得分:1)

如果您使用播放光滑插件,它将需要一个启动播放应用程序,以便能够调用使用该插件的数据库访问的代码,您可以确保使用WithApplication在测试中启动播放应用程序如文档中所述:http://www.playframework.com/documentation/2.3.x/ScalaFunctionalTestingWithSpecs2