scala - Scala Play Framework 2.6、Guice、Slick 3.2.3 根据请求动态更改数据库
问题描述
我有一个应用程序这些是堆栈
- 玩 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
根据请求参数更改参数
解决方案
这是可能的解决方案。
配置数据库
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)
}
}
}
}
推荐阅读
- android - 以编程方式打开首选项
- python - TensorFlow 服务与 contrib 操作
- json - 如何在 Jackson 中以特定格式显示小数(对于 JSON)
- ios - 如何从非越狱设备中提取 dyld_shared_cache?
- ios - SpriteKit 暂停场景 (Swift4.2)
- java - 抽象超类中的受保护字段是否应该在子类中使用 super 或 this 访问?
- xml - sed 用于搜索和替换 xml 文件中的文本
- reactjs - 如何在 React 中使用 Redux
- c++ - c++ 快速排序向量对作为遗传学习算法的一部分
- c - 将文件字符转换为大写