Slick 3.1.x JdbcProfile 错误的通用 DAO "value id is not a member of ..."

Slick 3.1.x Generic DAO for JdbcProfile error "value id is not a member of ..."

我正在尝试为我的 slick 代码生成模型创建一个 Slick 3.1.1 Generic DAO。但是,我遇到了最后一个找不到修复方法的编译错误。

整个项目在 GitHub play-authenticate-usage-scala and the relevant source code is in the GenericDao.scala 中可用。

编译错误如下:

[info] Compiling 16 Scala sources and 1 Java source to /home/bravegag/code/play-authenticate-usage-scala/target/scala-2.11/classes...
[error] /home/bravegag/code/play-authenticate-usage-scala/app/dao/GenericDao.scala:46: value id is not a member of type parameter ET
[error]     def findById(id: PK): Future[Option[ER]] = db.run(tableQuery.filter(_.id === id).result.headOption)
[error]                                                                           ^

基本上它不识别 Identifyable 特征下的 id 定义。顶级声明如下:

trait Identifyable[PK] extends Product {
  def id : PK
}

trait GenericDaoHelper {
  val profile: slick.driver.JdbcProfile
  import profile.api._

  class GenericDao[PK, ER <: Identifyable[PK], ET <: Table[ER], TQ <: TableQuery[ET]] @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)
      (tableQuery: TQ) extends HasDatabaseConfigProvider[JdbcProfile] {
    import driver.api._

    /**
      * Returns the matching entity for the given id
      * @param id identifier
      * @return the matching entity for the given id
      */
    def findById(id: PK): Future[Option[ER]] = db.run(tableQuery.filter(_.id === id).result.headOption)
}

PS:请注意,我使用的是最新的 Slick 3.1.1,这很重要,因为过去人们已经实现了类似的解决方案,但它们在不同版本之间发生了很大变化。

ET 是 table(Table[ER] 的子类型)。从错误中可以清楚地看出 ET 没有 Rep[PK]

trait IdentifyableTable[PK] extends Table[ER] {
  def id: Rep[PK]
}

而不是将 ET 声明为 Table[ER] 的子类型。将其声明为 IdentifyableTable[PK].

的子类型

像这样声明你的通用 dao

class GenericDao[PK, ER <: Identifyable[PK], ET <: IdentifyableTable[PK], TQ <: TableQuery[ET]] ....

我发现一个以前的 Slick 版本 CrudComponent gist implementation 不能完全照原样使用,而是通过将其适应最新的 Slick 3.1.x 它然后解决了 id 编译OP中描述的问题。解决方案基本上是重新安排模板类型及其范围。

最终的解决方案可以在文件GenericDao.scala

中找到