How to do I pass TableQuery as a Generic and then use it?

主宰稳场 提交于 2019-12-11 06:05:29

问题


I'm trying to template-out a TableQuery member but the path dependant types are messing me up. I've got a typical code-generated table like so:

trait TablesContainer {
    case class MembersRow(firstName:String, lastName:String)

    class Members(_tableTag: Tag) extends Table[MembersRow](_tableTag, Some("dbo"), "MEMBERS") {
        def * = (firstName, lastName) <> (MembersRow.tupled, MembersRow.unapply)

        val firstName: Rep[String] = column[String]("FIRM_NAME")
        val lastName: Rep[String] = column[String]("LAST_NAME")
    }
}

Then I try to create a class that will take a TableQuery (in the typical multi-db pattern) like so:

class TemplateHolder(profile: RelationalProfile) {
    import profile.api._

    class InsertionTemplate[T <: Table[E], E](tableQuery: TableQuery[T]) {
        def apply(insertRow:E) = {
          tableQuery += insertRow
        }
    }
}

Then I want to use it like so:

def template = new InsertionTemplate(TableQuery[TablesContainer.Members])

template.apply(MembersRow("Joe", "Bloggs"))

Only I get errors:

Error:(134, 28) inferred type arguments [com.test.TablesContainer.Members,Nothing] do not conform to class InsertionTemplate's type parameter bounds [T <: RelationalProfileConstants.this.profile.api.Table[E],E]
  def template = new InsertionTemplate(TableQuery[TablesContainer.Members])

and then this one:

Error:(134, 60) type mismatch;
 found   : slick.lifted.TableQuery[com.test.TablesContainer.Members]
 required: RelationalProfileConstants.this.profile.api.TableQuery[T]
    (which expands to)  slick.lifted.TableQuery[T]
  def template = new InsertionTemplate(TableQuery[TablesContainer.Members])

What am I doing wrong?


回答1:


The below code compiles without issues. The InsertionTemplate method was not able to infer type of E so explicitly providing the type parameter solved the issue. there could also be potential issues with your imported scopes. make sure you have the import statement import driver.api._ as shown below.

  trait Container1  {

    self: HasDatabaseConfigProvider[JdbcProfile] =>

    import driver.api._

    trait TablesContainer {
      case class MembersRow(firstName:String, lastName:String)
      class Members(_tableTag: Tag) extends Table[MembersRow](_tableTag, Some("dbo"), "MEMBERS") {
        def * = (firstName, lastName) <> (MembersRow.tupled, MembersRow.unapply)
        val firstName: Rep[String] = column[String]("FIRM_NAME")
        val lastName: Rep[String] = column[String]("LAST_NAME")
      }
    }
  }


  trait Container2 {

    self: HasDatabaseConfigProvider[JdbcProfile] with Container1 =>

    import driver.api._

    class InsertionTemplate[T <: Table[E], E](tableQuery: TableQuery[T]) {
      def apply(insertRow:E) = {
        tableQuery += insertRow
      }
    }

    class Run extends TablesContainer {
      // specify explicit type parameters.
      def template = new InsertionTemplate[Members,MembersRow](TableQuery[Members])
      template.apply(MembersRow("Joe", "Bloggs"))
    }
  }


来源:https://stackoverflow.com/questions/44184904/how-to-do-i-pass-tablequery-as-a-generic-and-then-use-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!