我正在使用 play-slick 和 slick进化来创建我的数据库。
我有以下配置
slick.dbs.default.profile="slick.jdbc.H2Profile$"
slick.dbs.default.db.driver="org.h2.Driver"
slick.dbs.default.db.url="jdbc:h2:mem:play;DB_CLOSE_DELAY=-1"
当我想使用 slick 本身对数据库进行操作时,这效果很好。但是,我想访问底层
javax.sql.Datasource
实例(我需要将其传递给另一个库,即 pac4js DbProfileService
)。
我尝试添加数据库名称的配置为
dbName="play"
,然后添加
@Provides
def dbProfileService(dbApi: DBApi): DbProfileService = {
new DbProfileService(dbApi.database(configuration.get[String]("dbName")).dataSource)
}
但是,注入似乎发生在进化脚本有机会运行之前,这会导致出现异常,指出无法找到
play
数据库。
有没有更好的方法来解决这个问题?
这是堆栈跟踪
aused by: java.lang.IllegalArgumentException: Could not find database for play
at play.api.db.slick.evolutions.internal.DBApiAdapter.$anonfun$database$1(DBApiAdapter.scala:32)
at scala.collection.immutable.Map$Map1.getOrElse(Map.scala:248)
at play.api.db.slick.evolutions.internal.DBApiAdapter.database(DBApiAdapter.scala:32)
at modules.SecurityModule.dbProfileService(SecurityModule.scala:53)
at modules.SecurityModule$$FastClassByGuice$$153731.GUICE$TRAMPOLINE(<generated>)
at modules.SecurityModule$$FastClassByGuice$$153731.apply(<generated>)
at com.google.inject.internal.ProviderMethod$FastClassProviderMethod.doProvision(ProviderMethod.java:260)
at com.google.inject.internal.ProviderMethod.doProvision(ProviderMethod.java:171)
at com.google.inject.internal.InternalProviderInstanceBindingImpl$CyclicFactory.provision(InternalProviderInstanceBindingImpl.java:185)
at com.google.inject.internal.InternalProviderInstanceBindingImpl$CyclicFactory.get(InternalProviderInstanceBindingImpl.java:162)
at com.google.inject.internal.SingleParameterInjector.inject(SingleParameterInjector.java:40)
at com.google.inject.internal.SingleParameterInjector.getAll(SingleParameterInjector.java:60)
at com.google.inject.internal.ProviderMethod.doProvision(ProviderMethod.java:171)
at com.google.inject.internal.InternalProviderInstanceBindingImpl$CyclicFactory.provision(InternalProviderInstanceBindingImpl.java:185)
at com.google.inject.internal.InternalProviderInstanceBindingImpl$CyclicFactory.get(InternalProviderInstanceBindingImpl.java:162)
at com.google.inject.internal.SingleParameterInjector.inject(SingleParameterInjector.java:40)
at com.google.inject.internal.SingleParameterInjector.getAll(SingleParameterInjector.java:60)
at com.google.inject.internal.ProviderMethod.doProvision(ProviderMethod.java:171)
at com.google.inject.internal.InternalProviderInstanceBindingImpl$CyclicFactory.provision(InternalProviderInstanceBindingImpl.java:185)
at com.google.inject.internal.InternalProviderInstanceBindingImpl$CyclicFactory.get(InternalProviderInstanceBindingImpl.java:162)
at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:50)
at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:146)
at com.google.inject.internal.MembersInjectorImpl.injectAndNotify(MembersInjectorImpl.java:101)
at com.google.inject.internal.Initializer$InjectableReference.get(Initializer.java:245)
at com.google.inject.internal.Initializer.injectAll(Initializer.java:140)
at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:180)
我还添加了一个断点,果然,那里只有
default
db,而不是我期望的 play
db。
问题出在键
dbName
的值上。当你在做的时候
configuration.get[String]("dbName")
您正在查找配置文件中名为
dbName
的键的值。在提供的示例中,该值为 play
。现在,看看完整的生产线,您会看到这个
@Provides
def dbProfileService(dbApi: DBApi): DbProfileService = {
new DbProfileService(
dbApi // trait play.api.db.DBApi
.database( // method from `DBApi`
configuration.get[String]("dbName") // getting the value of the key `dbName` from config file
)
.dataSource
)
}
您正在从
database
调用 DBApi
方法。有两个类混合了这种特性。一个是来自 play-slick-evolutions
的 DBApiAdapter,另一个是来自
play-jdbc
的 DefaultDBApi。我认为在你的情况下使用的是属于进化模块的模块。如果您查看正在调用的方法
database
的实现,两个类都具有相同的逻辑(因此,使用哪个实现并不重要)。
def database(name: String): Database = {
databaseByName.getOrElse(name, throw new IllegalArgumentException(s"Could not find database for $name"))
}
这意味着它将查找带有前缀
slick.dbs.<db name>
的键。根据您收到的错误消息
caused by: java.lang.IllegalArgumentException: Could not find database for play
at play.api.db.slick.evolutions.internal.DBApiAdapter.$anonfun$database$1(DBApiAdapter.scala:32)
您尝试查找带有前缀
slick.dbs.play
的数据库配置,并且 stracktrace 显示在这种情况下正在使用 evolutino 模块的实现。
要解决此问题,您有两种选择:
play
的值dbName
更改为default
slick.dbs.default
更改为 slick.dbs.play