2017-05-25 69 views
1

我想模板出一個TableQuery成員,但路徑依賴類型搞砸了我。我有一個典型的代碼生成的表像這樣:如何將TableQuery作爲泛型傳遞,然後使用它?

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") 
    } 
} 

然後我試圖創建一個類,將採取TableQuery(在典型的多DB模式),像這樣:

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

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

然後我想使用它,像這樣:

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

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

只有我得到的錯誤:

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

然後這一個:

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

我在做什麼錯?

回答

3

下面的代碼編譯沒有問題。 InsertionTemplate方法無法推斷E的類型,所以明確提供類型參數解決了問題。您的導入範圍也可能存在潛在問題。請確保您有如下所示的進口說明import driver.api._

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")) 
    } 
    } 
+0

Thanks rouge-one!任何想法如果你不能把TablesContainer和InsertionTemplate放在同一個父特徵中怎麼做?我不能這樣做,因爲Slick通過Codegen生成它(技術上我可以擴展Codegen,但這是一個更大的難題)。這是特別有問題的,因爲Slick在TablesContainer類中使用slick.driver.JdbcProfile,我想使用RelationalProfile,因此我可以在內存中進行測試。 – ChoppyTheLumberjack

+0

@ChoppyTheLumberjack我們可以將特質分成兩個不同的特質,如果這有助於你。我已經更新了答案。關於使用RelationalProfile ..你可以使用JDBCProfile,並且仍然在內存中進行測試。我使用H2數據庫。 –

+0

再次感謝@ rogue-one。所以看來,解決這個問題的唯一方法就是在包含TablesContainer的事物的頂層上粘貼一個圖層。那是對的嗎? – ChoppyTheLumberjack

相關問題