与通用存储库方法作斗争
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。
我有一个语言模型,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。