静静地删除可空数据库列

时间:2018-08-08 15:07:29

标签: scala slick

我有一个名为Campaigns的对象的数据库,其中包含三个字段:

  • Id(int,不可为空)
  • 版本(int,不可为空)
  • 资料(文本,可为空)

让我们CampaignsRow调用相应的光滑实体类

当我从Campaigns中选择一行时,我并不总是需要阅读包含大量文本的内容。

但是,我非常想在代码库中使用CampaignsRow类而不是元组,因此有时可以删除Stuff列,同时保留原始类型

基本上,我正在尝试编写以下函数:

  //Force dropping the Stuff column from the current Query
  def smallCampaign(campaigns: Query[Campaigns, CampaignsRow, Seq]): Query[Campaigns, CampaignsRow, Seq] = {

    val smallCampaignQuery = campaigns.map {
      row => CampaignsRow(row.id, row.version , None : Option[String]) 
    } 
    smallCampaignQuery /* Fails because the type is now wrong, I have a Query[(Rep[Int], Rep[Int], Rep[Option[String]), (Int, Int, Option[String], Seq] */
  }

任何想法如何做到这一点?我怀疑这与slick中的Shape有关,但是我找不到资源来开始理解此类,并且slick源代码对于我来说太复杂了。

2 个答案:

答案 0 :(得分:2)

实际上,您已经在def *(默认映射)中几乎完成了所需的操作。您可以在map方法中使用相同的工具。您的两个工具是mapTo<>

您已经发现,mapTo方法仅在您的case类与元组的形状完全匹配时才可以使用,因此,如果您只想为此目的使用特殊case类:

case class CampaignLite(id: Int, version: Int)

val smallCampaignQuery = campaigns.map {
  row => (row.id, row.version).mapTo[CampaignLite]
}

当您要重用现有类时,可以编写自己的转换函数,而不必使用标准的tupledunapply并将其传递给<>

object CampaignRow {
  def tupleLite(t: (Int, Int)) = CampaignRow(t._1, t._2, None)
  def unapplyLite(c: CampaignRow) = Some((c.id, c.version))
}

val smallCampaignQuery = campaigns.map {
  row => (row.id, row.version) <> (CampaignRow.tupleLite, CampaignRow.unapplyLite)
}

这为您提供了最大的灵活性,因为您可以在转换函数中做任何您想做的事,但是它比较罗word。

由于rowCampaigns表的一个实例,如果需要定期使用它,可以随时在*旁边定义它。

class Campaigns ... {
  ...
  def * = (id, version, stuff).mapTo[CampaignRow]
  def liteMapping = (id, version) <> (CampaignRow.tupleLite, CampaignRow.unapplyLite)
}

val liteCampaigns = campaigns.map(_.liteMapping)

参考:Essential Slick 3, section 5.2.1

答案 1 :(得分:1)

如果我正确理解了您的要求,则可以考虑使CampaignRow扩展Campaigns并提供双向映射,从而使Campaigns成为为Table[CampaignRow]表类建模的案例类。用于*投影:

case class CampaignRow(id: Int, version: Int, stuff: Option[String])

class Campaigns(tag: Tag) extends Table[CampaignRow](tag, "CAMPAIGNS") {
  // ...
  def * = (id, version, stuff) <> (CampaignRow.tupled, CampaignRow.unapply)
}

然后您应该可以执行以下操作:

val campaigns = TableQuery[CampaignRow]

val smallCampaignQuery = campaigns.map( _.copy(stuff = None) )

举一个相关的例子,这里是Slick doc