使用通用存储库方法苦苦挣扎

时间:2017-01-22 22:45:49

标签: scala generics slick-3.0

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

    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扩展,以摆脱对所有存储库/模型都应该相同的泛型检索方法。但遗憾的是到目前为止没有运气:

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

这里我收到一个错误&gt;&gt;需要类类型,但发现了Base.this.EntityTable

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

    ...

    override type EntityTable = LanguageTable
  }

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

1 个答案:

答案 0 :(得分:1)

您的基表定义不会像那样工作。你需要类类型,也许你应该使用泛型。而且,不是创建多个抽象,而是从一个抽象开始,然后从那里进化。尝试以下几点:

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]) {
    //...
}

首先编译所有内容,然后开始一次添加一个类。