2013-10-12 27 views
1

根据DRY,我试图避免在Slick表定义中插入和更新逻辑的重复。我尝试这样做:slick reusable InsertAndUpdate trait

trait Entity { 
    def id: Option[Int] 
} 

case class BankRekening(id: Option[Int], nummer: String, omschrijving: String) extends Entity{ 
} 

object BankRekeningen extends Table[BankRekening]("bankrekening") with InsertAndUpdate[BankRekening] { 
    def id = column[Int]("id", O.PrimaryKey, O.AutoInc) 
    def nummer = column[String]("nummer") 
    def omschrijving = column[String]("omschrijving") 
    def * = id.? ~ nummer ~ omschrijving <> (BankRekening, BankRekening.unapply _) 
    def idx_nummer = index("idx_nummer", nummer, unique = true) 
} 

trait InsertAndUpdate[T <: Entity] { 
    this: Table[T] => 

    def id: scala.slick.lifted.Column[Int] 

    def insert(obj: T): T = { 
     obj.copy(id = Some(this.returning(this.id) insert obj)) 
    } 
} 

现在,编译器抱怨在最后陈述“OBJ”,他说:找不到类型scala.slick.lifted.TypeMapper的证据参数内含价值[T]

有任何想法吗?

+0

只是一个预感,但你是否已经导入了'scala.slick.driver。 .simple._'? –

+1

华夫悖论,是的,他有哪些是“问题”的中间原因(最终导致Scalac产生误导性错误信息)。 – cvogt

回答

2

简单的答案:您尝试在T上调用复制,该复制没有复制方法。

很长的答案:不幸的是,Scalac,Scala编译器让我们(无意)高误插错误信息。你应该看到一个错误value copy is not a member of T。在copy的情况下,Scalac以某种方式吞下该消息,因为Slick将其置于范围之内。这里是一个缩小再现:

object simple{ 
    implicit def intColumnType: TypedType[Int] = null 
    implicit def valueToConstColumn[T : TypedType](v: T) = ConstColumn(v) 
} 
import simple._ 
trait TypedType[T] 
case class ConstColumn[T](v: T){ 
    def bar = 5 
} 

trait InsertAndUpdate[T] { 
    def insert(obj: T): T = { 
     5.copy() // <- unexpected, but is valid and compiles fine 
     5.bar // compiles fine 

     obj.bar // error: value bar is not a member of type parameter T 
       // error: could not find implicit value for evidence parameter of type TypedType[T] 

     obj.copy() // error: could not find implicit value for evidence parameter of type TypedType[T] 
    } 
} 

正如你可以看到消息以某种方式吞噬了copy。此外,我没有找到消息could not find implicit value for evidence parameter of type TypedType[T]有帮助。我创建了一个Scala门票来解决这个问题:https://issues.scala-lang.org/browse/SI-7907

+0

我现在看到,实体不是案例类,而是特质。有一个案例类,因此预计将有复制方法。 5.copy编译是因为5'是一个case类'...? – JointEffort

+0

您不能从案例类继承,因此实体不能成为案例类。 5不是案例课。 5.copy()工作,因为ConstColumn是一个案例类,编译器应用valueToConstColumn将5转换成具有复制方法的东西。 valueToConstColumn适用于Int,因为范围中存在隐式的TypedType [Int]。但是在复制方法的情况下,这种转换可能不是用户想要的。也许我们应该将ConstColumn更改为Slick中的普通类,以避免这种情况。 – cvogt