1

I'm trying to create a Slick 3.1.1 Generic DAO for my slick code-generated model. However, I'm facing one last compilation error that can't find how to fix.

The whole project is available in GitHub play-authenticate-usage-scala and the relevant source code is in the GenericDao.scala.

The compiler error is the following:

[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]                                                                           ^

Basically it doesn't recognize the id definition under the Identifyable trait. The top declarations are the following:

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: note that I'm working with the latest Slick 3.1.1 this is critical because people have implemented similar solutions in the past but they change quite a bit from version to version.

SkyWalker
  • 13,729
  • 18
  • 91
  • 187

2 Answers2

2

ET is a table (subtype of Table[ER]). From the error it is clear that ET does not have Rep[PK]

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

Instead of declaring ET as subtype of Table[ER]. Declare it as subtype of IdentifyableTable[PK].

Declare your generic dao like this

class GenericDao[PK, ER <: Identifyable[PK], ET <: IdentifyableTable[PK], TQ <: TableQuery[ET]] ....
Nagarjuna Pamu
  • 14,737
  • 3
  • 22
  • 40
  • It is close but it doesn't really solve the problem ... for example User model is generated as `class User(_tableTag: Tag) extends Table[UserRow]` so `ET` is in this case `User` and its id generated as `val id: Rep[Long]` – SkyWalker Nov 28 '16 at 21:35
  • @GiovanniAzua You need to make `def id: Rep[PK]` available with the type `ET`. I don't think its generated dynamically – Nagarjuna Pamu Nov 28 '16 at 21:37
1

I found a previous Slick version CrudComponent gist implementation that can't be taken exactly as is but by adapting it to the latest Slick 3.1.x it then solves the id compilation issue described in the OP. The solution was basically a rearrangement of the template types and their bounds.

The final solution can be found in file GenericDao.scala

SkyWalker
  • 13,729
  • 18
  • 91
  • 187
  • The second link ("final solution") is broken. Could you make it available on GitHub if you managed to clone it on time? – JulienD Dec 20 '16 at 10:52
  • Hahah fixed it ... now works ... I refactored the generic part of the dao under generic that's all. In fact, you may copy paste the whole code under generic because should not have any other dependency – SkyWalker Dec 20 '16 at 10:58
  • Thanks! that's why I decided to rewrite the usage example ... I settle for nothing but perfection :D you can also checkout the code under dao for sample extensions ... there I cover many Slick use-cases specially in the `UserDao` extension – SkyWalker Dec 20 '16 at 11:08
  • This worked perfectly, except that the Entity and Identifyable traits must be applied to all tables auto-generated by the schema code generator, which is not ideal, so I preferred cluttering my own code with a `def getId(table: ): Rep[Int] = table.id` everywhere. Also I could not replace the `PK` type `Long` to `Int` because of missing implicits (implicits are a real pain), so I made the type explicit. But you saved me from despair.
    – JulienD Dec 22 '16 at 14:00
  • @JulienD in that project I customized the slick code gen to generate the needed extends etc. It is all automatic for me. Checkout the linked project under tests the Generator.scala file – SkyWalker Dec 22 '16 at 14:04