1

(这个问题是基于一个非常相似的先前请求帮助。随着 DAO 和多个数据库驱动程序的引入,同样的问题需要不同的方法,我希望保证一个新的 SO 问题。)

我有一个这样定义的class和光滑的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.defaultin提供的驱动程序和数据库 url 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)
  }

但是,如果我想定义一个可以作用于 a 的方法TableQuery[Foo]怎么办?像这样的东西:

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

问题

编写findByTitle方法的正确方法是什么,我应该把它放在哪里,以便我可以:

  • 以一种不会与作用于 的同名方法冲突的方式调用它TableQuery[Bar]。来自 OO,我觉得我想做类似的事情foos.findByTitle("someFoo"),但如果有更好的方法来实现这种功能风格,我愿意接受建议。
  • 从应用程序控制器调用它,以便查询将与我的db.defaulth2 驱动程序一起使用,并从我的测试中调用它,Specification以便它与我的db.testpostgres 驱动程序一起使用。

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

4

2 回答 2

2

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

当您收到有关缺少隐式的错误消息时,这意味着您遇到了库提供的类型检查失败,阻止您做错事,但这里不是这种情况。或者您只是忘记使隐式可用。有两种方法可以使隐式可用。将其导入到您收到错误消息的范围内。或者基本上将查找推迟到您的方法的调用站点。不知道哪一个适合玩。您要么需要从 play 导入隐式应用程序,要么需要val dao转换为方法并在隐式参数列表中请求隐式应用程序def dao(implicit app: Application) = ...。您也可以将 test 变成一个类并在那里请求它。

于 2014-07-10T07:01:53.033 回答
1

如果您使用 play slick 插件,它将需要一个启动的 play 应用程序才能调用使用该插件的 DB 访问的代码,您可以确保在测试中使用WithApplication文档中描述的启动 play 应用程序:http: //www.playframework.com/documentation/2.3.x/ScalaFunctionalTestingWithSpecs2

于 2014-07-10T07:01:25.723 回答