case class MyModel(
id: Option[Int],
title: String,
backStepId: Option[Int] = None,
backStep: Option[MyModel] = None,
...
)
所以我必须在我的模型上使用backStep属性。我使用的第一个backStepId
来保存数据并将其映射到另一个实例
MyModel
。我使用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
时,它会说:Type mismatch, expected: Option[MyModel], actual: Some[MyModel.type]
。但是我也将这种方法用于其他用例。例如Some(Seq()),每当我验证传入时
某些模型的数组/序列。
我在这做错了什么?提前谢谢!
答案 0 :(得分:1)
首先让我们总结一下,你想在这里实现的目标:
Some(MyModel)
,它将伴侣对象实例放在一个Option中(MyModel.type
是该伴随对象的一种类型)MyModel
具有递归定义(因为它引用自身),我想说这样做会很困难(而且很危险)。如果您的backStep
会创建,例如数据库中的循环依赖,你最终会得到fetch上的无限循环,因为ProvenShape里面没有比逻辑更复杂的地方,而是将元组来回映射到其他表示(并且解析另一个记录是更复杂的逻辑)。 p>
相反,我建议您将模型分为两部分:
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
。
由于Slick(据我所知)不支持递归查询,您需要使用SQL to define your query。
通过此类查询,您将获得Seq[MyModelRow]
。使用该seq,您可以将Row无需依赖项转换为Model,然后使用Row引用它并将其转换为模型引用新构建模型等等。
事情是,这不是一个简单的问题。想想这样的情况:
Model(id:234).backStep -> Model(id:6456).backStep -> Model(id:56756).backStep -> null
您使用unapply建模的是,如果您抓取Model(id:234)
,则应该Model(id:6456)
。除了持有假设,而这些假设必须持有Model(id:56756)
。你可能想要它。你可能不会。当然,我会谨慎地将其作为默认行为。
相反,您可能会考虑默认不提取deps。只需获取backStepId
并确定一旦到达该怎么办。对于那些特殊情况,当您确实需要所有依赖项设计一个单独的查询时 - 此查询可以使用原始SQL一次获取所有行,然后您可以手动链接它们。
如果性能无关紧要,而您希望获得类似Hibernate的良好体验,则可以创建扩展方法,使用Slick添加backStep
方法以获取依赖关系{{1} }。
您可能想要检查的其他选项,就是让unapply始终返回Future[Option[MyModel]]
None
,并添加单独的服务以“丰富它”。
因此,根据权衡和优先级,您可能希望采用不同的路线。你知道你最好使用案例,所以我建议创建一个原型分支并试验哪种方法(也许我没想到的)将是最有用的。就个人而言,我更喜欢复杂的递归查询,以提醒我,我不能只是通过电话垃圾邮件数据库而不会受到任何惩罚。