2013-03-02 52 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