代码之家  ›  专栏  ›  技术社区  ›  agusgambina

Scala Play Framework 2.6、Guice、Slick 3.2.3根据请求动态更改数据库

  •  1
  • agusgambina  · 技术社区  · 7 年前

    • 游戏2.6
    • 圭斯
    • 玩滑头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 基于请求参数的参数

    1 回复  |  直到 7 年前
        1
  •  1
  •   Konstantin Konyshev    7 年前

    下面是一些可能的解决方案。

    配置数据库

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

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