【问题标题】:Scala Play Framework 2.1 Slick 1.0 Cake Pattern Common Table FieldsScala Play Framework 2.1 Slick 1.0 Cake Pattern 常用表字段
【发布时间】:2013-03-22 01:35:47
【问题描述】:

我正在开发一个使用 Slick 1.0 和 cake 模式连接到 postgresql 数据库的项目。
就像现在一样,一切似乎都运行良好,但我还有很多表要添加,而且我意识到所有表都包含许多公共列。我希望能够制作一个包含公共字段的特征,但我无法弄清楚如何让它发挥作用。 (我是 scala 的新手,但我认为我的基础知识已经很好了。)

这是一个示例,希望能说明我想要做什么:

One.scala:

    package models.db.slick
    import java.util.UUID
    import play.api.db.slick.Profile
    case class One(common1:UUID, common2:String, unique1:String)
    trait OneComponent{this: Profile =>
      import profile.simple._
      object Ones extends Table[One]("One") with CommonColumns{
        def unique1 = column[String]("unique1")
        def * = common1 ~ common2 ~ unique1 <> (One.apply _, One.unapply _)
      }
    }

ColumnColumns.scala:

    package models.db.slick
    import java.util.UUID
    import play.api.db.slick.Profile
    trait CommonColumns{
      def common1 = column[UUID]("common1")
      def common2 = column[String]("common2")
    }

这不会编译,因为 ColumnColumns trait 不知道 column[T]。我尝试指定一个 self 类型的 Table,但我不知道如何获取 Table 对象,该对象本身位于 scala.slick.driver.BasicTableComponent 特征中。我还尝试指定一个实现列函数的 self 类型,例如:

    trait CommonColumns{ this => {def column[C](n: String, options:    
                                   scala.slick.lifted.ColumnOption[C]* )
                                   (implicit tm:scala.slick.lifted.TypeMapper[C]
                                    ): scala.slick.lifted.Column[C]}
    ...
    }

但这不起作用。我很可能在那个语法上有错误,但我找不到一个很好的例子来说明如何做到这一点。

你怎么看?有什么好方法可以完成这项工作吗?

【问题讨论】:

  • 尚未测试,但似乎 CommonColumns 必须扩展 Table[T] 或将其自身类型声明为 Table[T]。
  • 是的,这是我试图做的事情,但我不知道如何实际指定它是 Table[T] 类型。它说找不到类型表。在“Ones”中,我引用了 Table[T],因为 OneComponent 是 Profile 的自我类型。然后当试图找到 Table[T] 的定义位置时,它是 trait scala.slick.driver.BasicTableComponent 中的一个对象,我不知道如何在 CommonColumns 中使用它。我很确定这只是我缺乏 scala 知识。
  • 我才意识到我一直在说 Table[T] 是 Trait 中的一个 Object,但它实际上是 trait 中的一个抽象类。因此,如果我试图说 CommonColumns 是 slick.driver.BasicTableComponent.Table[T] 的自我类型,我会收到一条消息,说明 BasicTableComponent 是一个没有伴随对象的特征

标签: scala slick


【解决方案1】:

我想通了! 至少我认为我做到了。如果有人发现这有问题,请告诉我。

好的,我就是这样做的:

我将 CommonColumns 特征更改为:

    trait CommonColumnsComponent{ this:Profile =>
      import profile.simple._
      trait CommonColumns{ this:Table[_] =>
        def common1 = column[UUID]("common1")
        def common2 = column[String]("common2")
      }
    }

然后我将 OneComponent 更改为:

    trait OneComponent extends CommonColumnsComponent{this: Profile =>
      import profile.simple._
      object Ones extends Table[One]("One") with CommonColumns{
        def unique1 = column[String]("unique1")
        def * = common1 ~ common2 ~ unique1 <> (One.apply _, One.unapply _)
      }
    }

它成功了。

【讨论】:

  • 我几乎就是这样。 trait CommonColumns[T] { this:Table[T] ...... extends Table[One]("One") with CommonColumns[One]{ ...。我不确定,但您的解决方案似乎会错过可以在两个类之间共享的其他有趣的抽象。
  • 所以,我认为您的意思是我不应该将 CommonColumns 特征限制为仅是我将其混合到的表的一部分。那正确吗?我确实看到这种方式在技术上如何具有更大的灵活性,但我想不出任何我想要的情况。使用 CommonColumns[Two]{... 扩展 Table[One]("One") 意味着什么?
  • CommonColmns[X] 的一个简单用例:接收 common1 或 2 并返回 X 的查询,使用 [_] 您无法在 CommonColumns 中实现。
  • 对于extends Table[One]("One") with CommonColumns[Two]{,如果 One 和 Two 之间存在正确的继承关系,它会起作用(很可能 - 我不记得这种情况下的方差限制)。
  • 啊,好的。所以,然后我可以让 CommonColumns 根据我发送的类型设置不同的公共字段。
猜你喜欢
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
  • 2013-10-29
  • 1970-01-01
  • 2013-01-06
  • 2012-12-06
  • 2015-09-05
  • 2016-08-05
相关资源
最近更新 更多