SLICK 中带有伴生对象的映射投影 [英] mapped projection with companion object in SLICK

查看:46
本文介绍了SLICK 中带有伴生对象的映射投影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有嵌套的类/对象,并希望使用 SLICK 将它们存储(和检索)到数据库中.我知道使用 SLICK 映射投影将是关键.此外,我使用一个伴随对象在嵌套对象和平面结构(存储在 DB 表中)之间进行映射.我想做这样的事情(简化示例):

I have nested classes/objects and want to store (and retrieve) them in a database by using SLICK. I understand that with SLICK mapped projection would be key. Furthermore I use a companion object to map between nested objects and flat structure (to be stored in the DB table). I want to do something like this (simplified example):

case class Foo(id: Int, myBar: Bar)

case class Bar(myInt: Int, myString: String)

object Foo {
  def apply(id: Int, myInt: Int, myString: String): Foo = Foo(id, Bar(myInt, myString))

  override def unapply(f: Foo) = (f.id, f.myBar.myInt, f.myBar.myString)
}

object TTable extends Table[Foo]("FOO") {
    def id = column[Int]("id",  O.PrimaryKey)
    def myInt = column[Int]("myInt", O NotNull)
    def myString = column[String]("myString", O NotNull)

    def * = id ~ myInt ~ myString <> (Foo.apply _, Foo.unapply _)

    def query(db: Database, id: Int): Option[Foo] = db withSession { //s: Session =>
        (for { b <- TTable if b.id is id} yield b).firstOption
    }
}

但是编译失败并出现几个错误:方法 unapply 定义了两次"、对重载定义的引用不明确,两个方法都应用 [...] 匹配预期类型?"和重载方法值 <> 与替代品"

But the compilation fails with several errors: "method unapply is defined twice", "ambiguous reference to overloaded definition, both method apply [...] match expected type ?" and "overloaded method value <> with alternatives"

我发现了对映射投影的出色解释scala slick到目前为止我无法理解的方法"和使用 <> 映射到带有 Slick 中伴随对象的案例类",但没有一个建议的解决方案适合我.

I found this excellent explanation of mapped projection "scala slick method I can not understand so far" and "Mapped projection with <> to a case class with companion object in Slick" but none of the suggested solutions work for me.

推荐答案

代替 unapplyapply,您可以只传入满足您要求的 lambda:

Instead of unapply and apply, you could just pass in lambdas that do what you want:

  def * = id ~ myInt ~ myString <> (
    (id,myInt,myString) => Foo(id, Bar(myInt, myString)),    /* from a row to a Foo */
    (f:Foo) => Some((f.id, f.myBar.myInt, f.myBar.myString)) /* and back */)

这样,从表行到 case 类的映射保留在表定义中,并且 case 类保留为简单的 case 类,这还不错.

This way, the mapping from table rows to case classes stays in the table definition, and the case classes stay as simple case classes, which isn't too bad.

另一种方法是不为 Foo 使用 case 类,而是使用常规类,让您可以自由定义自己的 apply在伴随对象中取消应用,如下所示:

The other way would have been to not use a case class for Foo, but a regular class instead which leaves you free to define your own apply and unapply in a companion object, like so:

// untested code
class Foo private (val id: Int, val myBar: Bar) 
case class Bar(myInt: Int, myString: String)
object Foo {
  def apply(id: Int, myInt: Int, myString: String): Foo = new Foo(id, Bar(myInt, myString))
  def unapply(f: Foo) = Some((f.id, f.myBar.myInt, f.myBar.myString))
}

如果你想做 def * = id ~ myInt ~ myString (Foo.apply _, Foo.unapply _)

您会在一定程度上获得类似案例类的用法,但您可能会错过其他好东西就像在实际案例类中免费使用 equalstoString 一样.我宁愿保留 case 类(以及它们的默认 apply unapply),这样它们就可以被视为正常约定中的代数数据类型.

You'll get case-class-like usage to an extent, but you might miss the other nice stuff like having equals and toString for free as with actual case classes. I'd rather keep the case classes (and their default apply unapply) so they can be treated as algebraic data types in the normal convention.

这里真正的问题是 case 类有自己的 unapply 所以你不能(据我所知)在你的伴生类中有类似的方法(相同的名称和相同的参数).您可以简单地使用另一个方法名称.毕竟,你想做的不是在语义上等同于 unapply 反正:

The real issue here is that case classes have their own unapply so you can't (as far as I know) have a similar method (same name and same arguments) in your companion class. You could simply just use another method name. After all, what you want to do isn't semantically equivalent to unapply anyway:

object Foo {
  def fromRow(id: Int, myInt: Int, myString: String): Foo = Foo(id, Bar(myInt, myString))
  def toRow(f: Foo) = Some((f.id, f.myBar.myInt, f.myBar.myString))
}

然后在您的表架构中:

def * = id ~ myInt ~ myString <> (Foo.fromRow _, Foo.toRow _)

这篇关于SLICK 中带有伴生对象的映射投影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆