关于scala:在Play Slick中分配动态注入的数据库名称

Assign dynamically injected database name in Play Slick

我有以下Play Slick DAO课程。请注意,数据库配置是常量control0001。 DAO具有函数readUser,该函数根据其用户ID读取用户:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class UsersDAO @Inject()(@NamedDatabase("control0001")
    protected val dbConfigProvider: DatabaseConfigProvider)
                  extends HasDatabaseConfigProvider[JdbcProfile] {

   import driver.api._

   def readUser (userid: String) = {
      val users = TableQuery[UserDB]
      val action = users.filter(_.userid === userid).result
      val future = db.run(action.asTry)
      future.map{
        case Success(s) =>
          if (s.length>0)
            Some(s(0))
          else
            None
        case Failure(e) => throw new Exception ("Failure in readUser:" + e.getMessage)
      }
   }
}

而不是在@NamedDatabase("control0001")中具有常量,我需要数据库是可变的。在应用程序中,我在application.conf中配置了多个数据库(control0001control002等)。根据变量值,我需要确定要在DAO中使用的数据库。所有数据库都是相似的,并且具有相同的表(每个数据库中的数据都不同)。

以下Play类调用DAO函数,但首先需要确定要注入的数据库名称:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class TestSlick  @Inject()(dao: UsersDAO) extends Controller  {

  def test(someCode: Int, userId: String) = Action { request =>

    val databaseName = if (someCode == 1)"control0001" else"control0002"

    // Run the method in UsersDAO accessing the database set by databaseName

    val future = dao.readUser(userId)
    future.map { result =>
      result match {
        case Some(user) => Ok(user.firstName)
        case _ => Ok("user not found")
      }
    }
  }        
}

如何在Play Slick中实现?


您可以尝试初始化覆盖默认配置的slick db对象:

val db = Database.forURL("jdbc:mysql://localhost/" + databaseName, driver="org.h2.Driver")

slick docs中的更多信息http://slick.lightbend.com/doc/3.0.0/database.html


在这种情况下,不要尝试使用Play的运行时依赖项注入实用程序,而应直接在DAO中使用SlickApi并将数据源名称传递给dbConfig(DbName(name))方法。要获得SlickApi,请混合SlickComponents特性:

1
2
3
4
5
6
7
8
9
10
11
class UsersDAO extends SlickComponents {

  def readUser(userid: String, dbName: String) = {
    val users = TableQuery[UserDB]
    val action = users.filter(_.userid === userid).result

    val dbConfig = slickApi.dbConfig(DbName(dbName))
    val future = dbConfig.db.run(action.asTry)
    ...
  }
}

然后在您的控制器中:

1
2
3
4
5
6
def test(someCode: Int, userId: String) = Action { request =>

  val databaseName = if (someCode == 1)"control0001" else"control0002"
  val future = dao.readUser(userId, databaseName)
  ...
}