2013-03-02 51 views
5

使用Slick,我試圖將數據庫表項直接投影到它們表示的案例類。繼example in the documentation,我設置成使用<>操作映射的投影:將帶有<>的映射投影映射到帶有伴隨對象的案例類別Slick

case class SomeEntity3(id: Int, entity1: Int, entity2: Int) 

val SomeEntityTable = new Table[SomeEntity3]("some_entity_table") { 
    def id = column[Int]("id", O.PrimaryKey, O.AutoInc) 
    def entity1 = column[Int]("entity1") 
    def entity2 = column[Int]("entity2") 

    def * = id ~ entity1 ~ entity2 <> (SomeEntity3, SomeEntity3.unapply _) 
} 

現在,我想一些靜態常量和輔助方法添加到SomeEntity3。爲此,我創建了一個伴侶對象。但只要我包括線

object SomeEntity3 

*說一些難以辨認的關於「重載方法值<>替代品」的定義,一個漂亮的野生多行錯誤彈出。

伴侶對象如何與Slick中的雙向映射關聯,並且可以以某種方式實現我的目標?

回答

8

播對象通常是從外殼類的第一個參數列表的情況下的類的功能。所以,如果你有

case class Fnord(a: A, b: B, c: C)(d: D) 

Scala編譯器會自動生成同伴對象類似

object Fnord extends ((A, B, C) => Fnord) { 
    ... 
} 

現在,只要你明確地拼寫出一些關於伴侶反對自己,編譯器不再生成FunctionN延伸thingy。因此,大多數時候自己添加它是一個好主意。在你的情況,這將意味着定義,像這樣的SomeEntity3同伴:

object SomeEntity3 extends ((Int, Int, Int) => SomeEntity3) { 
    ... 
} 

有此行爲(長期開放)的問題,也: https://issues.scala-lang.org/browse/SI-3664

9

修復的方法是非常簡單:case類

def * = id ~ entity1 ~ entity2 <> (SomeEntity3.apply _, SomeEntity3.unapply _) 
+0

這並不工作,確實如此。任何關於拼寫爲什麼明確應用的解釋都是需要的,並在此解決問題? – notan3xit 2013-03-03 13:27:24

+1

明確地將apply方法轉換爲函數(eta擴展)會產生'(Int,Int,Int)=> SomeEntity3',即伴隨對象應該放在第一位的類型。更一般地說,將一個函數對象的apply方法轉換成一個「新」函數對象產生與原始函數相同的類型。 – 2013-03-03 13:36:34

+0

由於某些原因,當您有伴侶對象時,scalac會感到困惑,並且不會解除對象的應用。 – pedrofurla 2013-03-03 14:03:19

1

另一種方式來做到這一點是把對象將方法應用到元組中並將其傳遞給<>,如下所示。

package models 

import play.api._ 
import play.api.libs.json._ 
import scala.slick.driver.H2Driver.simple._ 

case class User(
    name: String, 
    id: Option[Int] = None 
) 

object User { 
    implicit val format = Json.format[User] 
} 

class UserTable(tag: Tag) extends Table[User](tag, "USERS") { 
    def id = column[Int]("ID", O.PrimaryKey, O.AutoInc) 
    def name = column[String]("NAME", O.NotNull) 

    def * = (name, id.?) <> ((User.apply _).tupled, User.unapply) 
} 

object Users extends TableQuery(new UserTable(_)) { 
    val findByID = this.findBy(_.id) 
} 
0

就個人而言,從殼體類部分施加apply方法不能與我的設置和油滑3.0。

然而,這工作,穴居到適當tupled方法間接地:

class WidgetTable(tag: Tag) extends Table[WidgetEntity](tag, "widget_tbl") { 

    def id = column[Int]("id",O.PrimaryKey) 
    def foo = column[String]("foo") 

    override def * = (id,foo) <> ((WidgetEntity.apply _).tupled,WidgetEntity.unapply) 
} 

查看完整的細節:https://stackoverflow.com/a/38589579/564157