由于类型推断问题,我很难在我的案例类和数据库表之间获得自定义映射。这是我得到的一个例子,它只是原始用例的一个极度精简的版本,但它应该足以说明问题:
case class Example(id: Int, aString: String, optional: Option[Int], extra: String)
class Examples(tag: Tag) extends Table[Example](tag, "EXAMPLE") {
def id = column[Int]("ID", O.AutoInc, O.PrimaryKey)
def aString = column[String]("A_STRING")
def optional = column[Option[Int]]("AN_OPTIONAL")
override def * = (id, aString, optional) <> (constructExample, extractExample)
private def constructExample(id: Int, aString: String, optional: Option[Int]): Example = {
Example(id, aString, optional, "MY EXTRA DATA")
}
private def extractExample(e: Example): Option[(Int, String, Option[Int])] = {
Some((e.id, e.aString, e.optional))
}
}
这里我定义了两个自定义函数来处理我的case类和数据库行之间的转换。问题是<>
方法无法推断构造的元组类型,给出以下错误:
错误:(60,50)类型不匹配; found:(Int,String,Option [Int])=&gt; SlickExampleRepository.this.Example 要求:? =&GT; ? 覆盖def * =(id,aString,optional)&lt;&gt; (constructExample,extractExample)
在Slick docs中可以找到以下内容:
它也可以与任意映射函数一起使用。在这些情况下,在左侧的元组上调用.shaped可能很有用,以便正确推断其类型。否则,您可能必须向映射函数添加完整类型注释。
没有它的例子,但我继续尝试以下方法:
override def * = (id, aString, optional).shaped <> (constructExample, extractExample)
这似乎只能部分解决问题,给出以下错误:
错误:(60,57)类型不匹配; found:(Int,String,Option [Int])=&gt; SlickExampleRepository.this.Example required:((Int,String,Option [Int]))=&gt; ? 覆盖def * =(id,aString,optional).shaped&lt;&gt; (constructExample,extractExample)
所以我发现最后的解决方法是更改constructExample
函数的签名以接收元组并返回一个Example对象,如下所示:
private def constructExample(tuple: (Int, String, Option[Int])): Example = {
Example(tuple._1, tuple._2, tuple._3, "MY EXTRA DATA")
}
但这是非常可怕和容易出错的,因为我们正在定义可能很长的元组并使用._1
等来访问它的元素。有关如何以nice
方式使其工作的任何提示?
非常感谢
答案 0 :(得分:0)
您应该使用以下方式定义*
投影:
override def * = (id, aString, optional) <> ((constructExample _).tupled, extractExample)
constructExample _
会将您的私有方法转换为函数,.tupled
会将带有3个参数的函数转换为带有Tuple3
个参数的函数。