与通用存储库方法作斗争

Struggling with generic(s) repository methods

我有一个语言模型,table 和存储库。到目前为止这有效:

    package repositories

import javax.inject.Inject

import Helper
import model.{Language, LanguageModel}
import play.api.Logger
import play.api.cache.SyncCacheApi
import slick.jdbc.JdbcProfile

import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success}

class LanguageRepository @Inject()(cache: SyncCacheApi, jdbcProfile: JdbcProfile, implicit val executionContext: ExecutionContext)
{
  private val model = new LanguageModel(jdbcProfile)

  import jdbcProfile.api._

  def all(userName: String): Future[Seq[Language]] =
  {
    cache.get[Future[Seq[Language]]](buildCacheKey(userName)) match
    {
      case Some(x) => {Logger.info("[LanguageRepository](all) Found something in cache"); x}
      case None => {
        Logger.info("[LanguageRepository](all) Nothing useful to be found in cache, calling database now")
        val result = retrieve(userName)
        result.onComplete{
          case Success(value) => if(!value.isEmpty) cache.set(buildCacheKey(userName), result)
          case Failure(e) => ()
        }

        result
      }
    }
  }

  private def retrieve(userName: String): Future[Seq[Language]] =
  {
    // TODO extract this to a repositoryTrait and implement fallbacks etc
    val db = Database.forURL(Helper.getDbUrl(), driver = Helper.getDbDriver())

    db.run(model.all.result)
  }

  private def buildCacheKey(userName: String): String = s"$userName.languages"
}

现在我正在为过去的今天和现在的我而苦苦挣扎。

所以我创建了这个特性,并希望通过 LanguageRepository 对其进行扩展,以摆脱对所有 repositories/models 都应该相同的通用检索方法。但遗憾的是到目前为止没有运气:

trait Repository
{
  type Entity
  val model: Base
  val profile: JdbcProfile

  import profile.api._

  protected def retrieve(userName: String): Future[Seq[Entity]] =
  {
    val db = Database.forURL(Helper.getDbUrl(), driver = Helper.getDbDriver())      
    db.run(model.all.result)
  }
}

这是基地:

trait Base
{
  val dbProfile: JdbcProfile
  import dbProfile.api._

  type Entity
  type EntityTable <: Table[Entity]
  lazy val all = TableQuery[EntityTable]
}

这里我得到一个错误 >> class 需要输入但 Base.this.EntityTable 找到

class LanguageModel(databaseProfile: JdbcProfile) extends Base
  {
    override val dbProfile: JdbcProfile = databaseProfile
    import dbProfile.api._

    ...

    override type EntityTable = LanguageTable
  }

存储库本身也没有编译,因为类型不匹配。有很多问题,我不知道从哪里开始解决它们。

您的基本 table 定义不会那样工作。您需要 class 类型,也许您应该改用泛型。此外,与其创建多个抽象,不如从一个抽象开始,然后从那里发展。沿着这些方向尝试:

class Repository[A, B <: Table[A]](t: TableQuery[B]) {
    val model = t
    //protected def retrieve ..
}

class LanguageModel(databaseProfile: JdbcProfile) extends Repository[Language, LanguageTable](TableQuery[LanguageTable]) {
    //...
}

首先编译所有内容,然后开始添加抽象,一次 class。