【问题标题】:Mapped projection with <> to a case class with companion object in Slick使用 <> 将投影映射到 Slick 中带有伴随对象的案例类
【发布时间】:2013-03-02 14:37:32
【问题描述】:

使用 Slick,我试图将数据库表条目直接投影到它们所代表的案例类中。在example in the documentation 之后,我使用&lt;&gt; 运算符设置了映射投影:

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 中的双向映射有何关系?我能否以某种方式实现我的目标?

【问题讨论】:

    标签: scala slick


    【解决方案1】:

    修复很简单:

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

    【讨论】:

    • 这确实有效。需要任何关于为什么拼写明确适用的解释并在此处解决问题?
    • 将 apply 方法显式转换为函数(eta 扩展)会产生 (Int, Int, Int) =&gt; SomeEntity3,即伴随对象首先应该是的类型。更一般地说,将函数对象的 apply 方法转换为“新”函数对象会产生与原始函数相同的类型。
    • 由于某种原因,当您有一个伴随对象并且没有解除对象的应用时,scalac 会感到困惑。
    【解决方案2】:

    案例类的伴随对象通常是从案例类的第一个参数列表到案例类的函数。所以如果你有

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

    Scala 编译器会自动生成类似于

    的伴随对象
    object Fnord extends ((A, B, C) => Fnord) {
      ...
    }
    

    现在,只要您自己明确地拼写出有关伴生对象的内容,编译器就不再生成 FunctionN 扩展的东西。因此,大多数时候自己添加它是个好主意。在您的情况下,这意味着像这样定义 SomeEntity3 的同伴:

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

    这种行为也存在一个(长期开放的)问题: https://issues.scala-lang.org/browse/SI-3664

    【讨论】:

      【解决方案3】:

      另一种方法是将对象的 apply 方法转换为元组并将其传递给 ,如下所示。

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

      【讨论】:

        【解决方案4】:

        就个人而言,案例类中部分应用的apply 方法不适用于我的设置和Slick 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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-04-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-02-03
          • 1970-01-01
          • 2014-09-03
          • 1970-01-01
          相关资源
          最近更新 更多