【问题标题】:PlayFramework: how to inject database objectPlayFramework:如何注入数据库对象
【发布时间】:2017-01-02 18:26:39
【问题描述】:

我正在使用 anorm 作为游戏框架,并且我有以下服务类:

@javax.inject.Singleton
class ProductService @Inject() (dbApi: DBApi) {

  private val DB = dbApi.database("default")

  def save(product: Product) = {
    DB.withConnection { implicit connection =>
      ....
    }
  }
}

这里有两个问题:

1) 我不想在每个服务类中添加private val DB = dbApi.database("default") 行。抽象这个的最好方法是什么?

2) 我还想配置数据源,以便在编写集成测试时通过测试数据源

测试类:

import models.ProductService
import org.scalatestplus.play.{OneAppPerSuite, PlaySpec}
import play.api.db.Databases

class ProductSpec extends PlaySpec with OneAppPerSuite {

  var productService: ProductService = app.injector.instanceOf(classOf[ProductService])

  Databases.withDatabase(
    driver = "com.mysql.jdbc.Driver",
    url = "jdbc:mysql://localhost/playtest",
    config = Map(
      "user" -> "test",
      "password" -> "demo"
    )
  ) { database =>
    import play.api.db.evolutions._
    Evolutions.applyEvolutions(database)

    "Product" should {
      "be retrieved by Id" in {
        val product = productService.get(23)
        product.get.name must equal("mobile")
      }
    }
  }

}

有什么建议吗?

【问题讨论】:

    标签: scala playframework


    【解决方案1】:

    您可以注入database 对象本身而不是DBApi。顺便说一句,Guice 的最佳实践之一是inject only direct dependencies。所以,你的例子可能是这样的:

    import play.api.db.Database
    
    @Singleton
    class ProductService @Inject() (database: Database) {
    
      def save(product: Product) = {
        database.withConnection { implicit connection =>
          ....
        }
      }
    }
    

    当然,如果你想注入一个特定的数据库(而不是"default"),你可以像这样注释属性:

    import play.api.db.Database
    import play.db.NamedDatabase
    
    @Singleton
    class ProductService @Inject() (@NamedDatabase("customers") database: Database) {
    
      def save(product: Product) = {
        database.withConnection { implicit connection =>
          ....
        }
      }
    }
    

    并且,在您的测试中,您可以根据需要创建Database 并手动将其注入您的服务中。查看更多详情at the docs

    【讨论】:

    • 谢谢,这对服务类很有用。但是,我无法在集成测试中使用测试数据库。我已将我的测试课程添加到问题中。在应用进化时,它会尝试应用到“默认”数据库(在 application.conf 中配置)而不是测试套件中定义的测试数据库。非常感谢任何帮助。
    • @marcospereira 当我这样做时,我得到一个 Play error on startup: No implementation for play.api.db.Database was bound 异常。当我手动将名称默认添加到数据库时,我得到 No implementation for play.api.db.Database annotated with @play.db.NamedDatabase(value=default) was bound.
    • @decapo 您是否按照此处的说明添加了 jdbc 依赖项? playframework.com/documentation/2.7.x/…
    • @marcospereira 我做了,这干扰了光滑的插件,所以我删除了它。我忘记了确切的错误。我可能需要单独问一个问题,但是否可以在同一个项目中使用 Slick 和 jdbc?
    • 我不明白为什么不这样做。也许你有冲突错误?最好提出一个新问题并分享错误消息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    相关资源
    最近更新 更多