【问题标题】:Scala Play Framework 2.6, Guice, Slick 3.2.3 change database dynamically based on requestsScala Play Framework 2.6、Guice、Slick 3.2.3 根据请求动态更改数据库
【发布时间】:2018-11-23 23:23:40
【问题描述】:

我有一个应用程序,这些是堆栈

  • 播放 2.6
  • 吉斯
  • 玩 Slick 3.0.0

我正在尝试根据请求参数动态查询不同的数据库。

例如在application.conf

slick.dbs.default.profile = "slick.jdbc.H2Profile$"
slick.dbs.default.db.driver="org.h2.Driver"
slick.dbs.default.db.url="jdbc:h2:mem:test;MODE=MYSQL;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1;"

play.evolutions.db.default.enabled = true

slick.dbs.mydb2.profile = "slick.jdbc.H2Profile$"
slick.dbs.mydb2.db.driver="org.h2.Driver"
slick.dbs.mydb2.db.url="jdbc:h2:mem:test;MODE=MYSQL;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1;"

play.evolutions.db.mydb2.enabled = true

存储库

@Singleton
class UserRepositoryImpl @Inject() (@NamedDatabase("mydb2") dbConfigProvider: DatabaseConfigProvider)
  (implicit ec: ExecutionContext) extends UserRepository {

  val dbConfig = dbConfigProvider.get[JdbcProfile]

  import dbConfig._
  import profile.api._

  override def all: EitherT[Future, String, Seq[User]] = EitherT {
    db.run(UserTable.UserQuery.result.asTry).map {
      case Success(result) => {
        logger.debug(s"all success: $result")
        Right(result)
      }
      case Failure(error) => {
        val str = s"all error: ${error.getMessage}"
        logger.error(str, error)
        Left(str)
      }
    }
  }

}

有没有办法为每个请求更改dbConfigProvider?我想根据请求参数更改@NamedDatabase 参数

【问题讨论】:

    标签: scala playframework guice slick


    【解决方案1】:

    以下是可能的解决方案。

    配置数据库

    class Module(environment: Environment, configuration: Configuration) extends AbstractModule {
    
      def configure(): Unit = {
        bind(classOf[Config])
          .annotatedWith(Names.named("dbConfig"))
          .toInstance(configuration.underlying.getConfig("slick.dbs"))
    
        bind(classOf[String])
          .annotatedWith(Names.named("dbSchema1"))
          .toInstance("default")
    
        bind(classOf[String])
          .annotatedWith(Names.named("dbSchema2"))
          .toInstance("mydb2")
      }
    }
    

    创建助手类

    @Named("databaseService")
    @Singleton
    class DatabaseService @Inject()(@Named("dbConfig") dbConfig: Config,
                                    @Named("dbSchema1") schema1: String,
                                    @Named("dbSchema2") schema2: String) extends Logging {
    
      lazy val db1: JdbcBackend#DatabaseDef = {
        info("Init DB1")
        val database = DatabaseConfig.forConfig[MySQLProfile](schema1, dbConfig).db
        info("DB1 is ready")
        database
      }
    
      lazy val db2: JdbcBackend#DatabaseDef = {
        info("Init DB2")
        val database = DatabaseConfig.forConfig[MySQLProfile](schema2, dbConfig).db
        info("DB2 is ready")
        database
      }
    
      def run[R](action: DBIOAction[R, NoStream, Nothing])(implicit db: JdbcBackend#DatabaseDef): Future[R] = {
        import scala.concurrent.ExecutionContext.Implicits.global
        db.run(action).recoverWith {
          case exception: Throwable => {
            error("query failed", exception)
            Future.failed[R](exception)
          }
        }
      }
    
      def runDb1[R](action: DBIOAction[R, NoStream, Nothing]): Future[R] = {
        implicit val db = db1
        run(action)
      }
    
      def runDb2[R](action: DBIOAction[R, NoStream, Nothing]): Future[R] = {
        run(action)(db2)
      }
    }
    

    注入依赖并选择db运行

    @Singleton
    class UserRepositoryImpl @Inject() (databaseService: DatabaseService)
                                       (implicit ec: ExecutionContext) extends UserRepository {
    
      def all(param: Param): EitherT[Future, String, Seq[User]] = EitherT {
        val db = param match {
          case db1 => databaseService.db1
          case db2 => databaseService.db2
        }
        databaseService.run(UserTable.UserQuery.result.asTry)(db).map {
          case Success(result) => {
            logger.debug(s"all success: $result")
            Right(result)
          }
          case Failure(error) => {
            val str = s"all error: ${error.getMessage}"
            logger.error(str, error)
            Left(str)
          }
        }
      }
    }
    

    【讨论】:

    • 感谢您的回答,我正在尝试实现它,但我找不到 SchemaManagement 类
    • 确实,我更新了我的答案。可能你可以跳过这部分。它与数据库迁移有关。能否请您删除这些行并再次检查?
    • 抱歉耽搁了,虽然我已经回答了。它正在工作,我正在使用它。
    • 很高兴听到这个消息。谢谢你的回复。
    猜你喜欢
    • 2018-06-14
    • 1970-01-01
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多