2017-01-02 29 views
0

我使用的游戏框架ANORM和我有以下服务类:PlayFramework:如何注入数据库对象

@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") 
     } 
    } 
    } 

} 

有什么建议?

回答

2

您可以注入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

+0

谢谢,这对于服务类很有用。但是,我无法在Integration测试中使用测试数据库。我已经将我的测试课程添加到了问题中。在应用进化时,它会尝试应用到“默认”数据库(在application.conf中配置),而不是在测试套件中定义的测试数据库。任何帮助深表感谢。 –