在scala中将模型映射到Model.type

在scala中将模型映射到Model.type,scala,playframework,Scala,Playframework,我想我遇到了一个相当简单的问题。我有一个这样的模特 case class MyModel( id: Option[Int], title: String, backStepId: Option[Int] = None, backStep: Option[MyModel] = None, ... ) 所以我必须在我的模型上建立属性。我用来持久化数据并将其映射到另一个 我的模型。我使用backStep来验证传入的请求。我的特点是: t

我想我遇到了一个相当简单的问题。我有一个这样的模特

 case class MyModel(
      id: Option[Int],
      title: String,
      backStepId: Option[Int] = None,
      backStep: Option[MyModel] = None,
      ...
 )
所以我必须在我的模型上建立属性。我用来持久化数据并将其映射到另一个 我的模型。我使用backStep来验证传入的请求。我的特点是:

trait MyClassComponent extends AnotherClassComponent {
  self: HasDatabaseConfigProvider[JdbcProfile] =>
  import profile.api._
  class MyClass(tag: Tag) extends Table[MyModel](tag, "MyClass") {
    def id: Rep[Int] = column[Int]("id", O.PrimaryKey, O.AutoInc)
    def title: Rep[String] = column[String]("title")
    def backStepId: Rep[Option[Int]] = column[Option[Int]]("backStepId")
    def * : ProvenShape[MyModel] = (id.?, title, backStepId) <> ( {
      tuple: (Option[Int], String, Option[Int]) => MyModel(tuple._1, tuple._2, tuple._3, Some(<What do I need to fill in here?>))
    }, {
      x: MyModel=> Some((x.id, x.title, x.backStepId))
    })
  }
  val myModels: TableQuery[MyClass] = TableQuery[MyClass] // Query Object
}
在填写MyModel时,它显示:类型不匹配,预期:选项[MyModel],实际:一些[MyModel.Type]。然而,我也将这种方法用于其他用例。例如SomeSeq,每当我验证传入 某个模型的数组/序列。
我做错了什么?提前谢谢

首先,让我们试着总结一下,您希望在这里实现什么:

我猜错误来自于SomeMyModel,它将伴生对象实例放在选项MyModel中。type是伴生对象的一种类型 您希望MyModel在引用自身时具有递归定义, 您希望从数据库中获取并已填充它, 显然你想要一个统一的模型。 我想说,这样做是非常困难和危险的。如果您的backStep将在数据库中创建循环依赖项,那么您将在获取时得到无限循环,因为在ProvenShape中没有比来回将元组映射到其他表示形式和解析另一条记录更复杂的逻辑更复杂的地方

相反,我建议您将模型分为两部分:

case class MyModelRow(
    id: Option[Int],
    title: String,
    backStepId: Option[Int] = None,
    ...
)

case class MyModel(
    id: Int,
    title: String,
    backStep: Option[MyModel] = None,
      ...
)
这样,您可以获取MyModelRow,然后将其转换为MyModel

据我所知,它并不支持您需要使用的递归查询

通过这样的查询,您将获得Seq[MyModelRow]。有了这个seq,您可以将没有依赖项的行转换为模型,然后将引用它的行转换为引用新构建模型的模型,依此类推

问题是,这不是一个简单的问题。想想这样的情况:

Model(id:234).backStep -> Model(id:6456).backStep -> Model(id:56756).backStep -> null
您使用unapply建模的是,如果您获取Modelid:234,它应该具有Modelid:6456。除了持有假设,假设反过来必须持有Modelid:56756。你可能想要它。你可能不会。当然,我会小心地将其作为默认行为

<>你可能会考虑默认不取DEPS。只拿一张背带,等它到了再决定怎么处理。对于那些确实需要所有依赖项的特定情况,请设计一个单独的查询-此查询可以使用原始SQL一次获取所有行,然后可以手动链接它们

如果性能不受关注,而您希望有类似Hibernate的体验,您可以创建扩展方法,使用Slick添加backStep方法,以获取将来的依赖项[Option[MyModel]]

您可能需要检查的另一个选项是,简单地让unapply始终为backStep返回None,并添加单独的服务来丰富它

因此,根据权衡和优先级,您可能希望选择不同的路线。你知道你的用例是最好的,所以我建议创建一个原型分支,并尝试哪种方法——也许我提出的方法都不是最有用的。就我个人而言,我更喜欢显式递归查询的复杂性,以提醒我,我不能在没有任何惩罚的情况下,通过调用垃圾发送数据库