如何抽象光滑表之间的列定义?

时间:2019-07-09 14:53:22

标签: scala generics slick

我试图在现有的光滑应用程序的几个表中添加一个新列。所有表中的列均相同:在表中添加客户端ID,以在所有查询中启用客户端过滤功能。但是,在某些情况下,此ID是可选的:因此,我需要使用我们现有的查询来处理这两种情况。

当我尝试编写一些代码以使用新列在新客户端上进行过滤时,问题就来了。我想编写一种方法来包装所有修改后的表的表查询,并可以选择在客户端上进行过滤,但是当我尝试编写一种方法来完成此操作时,滑动会失败。

我尝试添加一个光滑扩展Table的抽象类来包装要在其中添加新客户栏的表格,如此

  abstract class ClientTable[T](tag: Tag, name: String) extends Table[T](tag,name)  {
    def client: Rep[Option[Int]]
  }

  class Feeds(tag: Tag) extends ClientTable[Feed](tag, "feeds") {
    def id: Rep[Int] = column[Int]("id", O.PrimaryKey, O.AutoInc)

    def name: Rep[String] = column[String]("name")

    ...

    def client: Rep[Option[Int]] = column[Option[Int]]("client")

    private val list = id :: name :: ... :: client :: HNil

    def * : ProvenShape[Feed] = list.mappedWith(Generic[Feed])
  }

但是,这似乎根本无法解决问题。

总体而言,我希望这种方法(或类似方法)可以工作:

  def tableView[T <: ClientTable[E], E] (tableQuery: TableQuery[E], clientId: Option[Int]) = {
    clientId match {
      case Some(id) => tableQuery.filter(_.client === id)
      case None => tableQuery
    }
  }
}

以便我可以用TableQuery替换查询中的private val xTable = tableView(TableQuery[X], clientId)定义,然后希望不必更改所有现有查询。

1 个答案:

答案 0 :(得分:1)

没有比未解决的堆栈溢出问题更糟糕的了!因此,这就是我最终解决此问题的方法。


我正在努力的方法最终是正确的,只是我的泛型略有错误。工作版本如下:

def tableView[T <: ClientTable[E], E <: ClientColumn](tableQuery: TableQuery[T], clientId: Option[Int]): Query[T, T#TableElementType, Seq] = {
    clientId match {
      case Some(id) => tableQuery.filter(_.client === id)
      case None => tableQuery
    }
  }

在表定义中,您都需要通过Table列实现来扩展client类型:

abstract class ClientTable[T](tag: Tag, name: String) extends Table[T](tag, name) {
  def client: Rep[Option[Int]] = column[Option[Int]]("client")
}

并用特质扩展行案例类,这样就将client字段添加到所有特例中

trait ClientColumn {
  def client: Option[Int]
}

case class Feed(id: Int = 0,
                name: String,
...
                client: Option[Int]) extends ClientColumn

现在tableView方法将按预期工作,尽管似乎仅在传入类型参数(例如val x = tableView[X, x](TableQuery[X], client))时使用,因为Scala似乎无法推断两个通用参数的类型

值得一提的是,我没有在表创建或ddl语句中使用Slick,而是在使用flyway。在这种情况下,对abstract classtrait使用此方法可能不起作用。

无论哪种方式,祝以后找到这个问题和答案的人都好运!