scala 如何在使用slick时获得播放器示例

ojsjcaue  于 6个月前  发布在  Scala
关注(0)|答案(1)|浏览(95)

我使用play-slick和slick evolutions来创建我的数据库。
我有以下配置

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示例(我需要将其传递到另一个库,即pac 4js DbProfileService)。
我尝试为数据库名称添加一个配置为dbName="play",然后添加

@Provides
  def dbProfileService(dbApi: DBApi): DbProfileService = {
    new DbProfileService(dbApi.database(configuration.get[String]("dbName")).dataSource)
  }


然而,注入似乎发生在evolution脚本有机会运行之前,这导致了一个异常,说无法找到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。

pcrecxhr

pcrecxhr1#

问题出在键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 
    )
}


您正在从DBApi调用database方法。有两个类混合了此trait。一个是从play-slick-evolutions调用的DBApiAdapter,另一个是从play-jdbc调用的DefaultDBApi。我认为在您的情况下使用的是属于evolution模块的那个。如果您查看您正在调用的方法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模块的实现。
要解决这个问题,你有两个选择:

  • 将键dbName的值play更改为default
  • 将前缀slick.dbs.default更改为slick.dbs.play

相关问题