【问题标题】:Assign dynamically injected database name in Play Slick在 Play Slick 中分配动态注入的数据库名称
【发布时间】:2018-05-09 15:14:26
【问题描述】:

我有以下 Play Slick DAO 类。请注意,数据库配置是一个常量control0001。 DAO 有一个函数readUser,它根据用户 id 读取用户:

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函数,但首先需要确定要注入的数据库名称:

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 中实现这一点?

【问题讨论】:

    标签: scala playframework slick slick-3.0 play-slick


    【解决方案1】:

    您可以尝试初始化 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

    【讨论】:

    • 我最终使用了您的想法,但我使用 JNDI 连接而不是 JDBC。使用连接后是否需要断开连接?
    • 我想不是,但请记住,你使用的是普通的 slick,而不是玩 slick 插件,请查看此示例 github.com/playframework/play-scala-isolated-slick-example
    • 我在这个例子中看不到是否需要断开 JNDI 连接
    【解决方案2】:

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

    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)
        ...
      }
    }
    

    然后在你的控制器中:

    def test(someCode: Int, userId: String) = Action { request =>
    
      val databaseName = if (someCode == 1) "control0001" else "control0002"
      val future = dao.readUser(userId, databaseName)
      ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-14
      • 2019-04-27
      • 2018-06-14
      • 1970-01-01
      • 2017-06-20
      • 1970-01-01
      相关资源
      最近更新 更多