用于多个TableQuery实例的Scala Slick单过滤器

时间:2016-01-12 22:25:43

标签: scala reflection slick-3.0 cake-pattern

我正在使用Scala Slick-3.1.0 lib

如何制作一个通用的Slick过滤器函数,将TableQuery实例作为输入并对其进行相同的光滑过滤?

我有几个表示存储在DB中的数据的案例类(例如两个)。 有些字段是相同的,因此类可能会扩展共同的祖先:

case class FirstData(symbol: String,
                     date: Timestamp,
                     firstField: Double) 

case class SecondData(symbol: String,
                      date: Timestamp,
                      secondField: String) 

它们中的每一个在DB中都有自己的SQL表,并由单独的Slick Table类表示。他们也有相同的主键:

class FirstDataTable(tag: Tag) extends Table[FirstData](tag, "firstData") {
    def symbol = column[String]("symbol")
    def date = column[Timestamp]("date")
    def firstField= column[Double]("firstField")
    def * = (symbol, date, firstField) <> ((FirstData.apply _).tupled, FirstData.unapply)
    def pk = primaryKey("pk_firstData", (symbol, date))
}

class SecondDataTable(tag: Tag) extends Table[SecondData](tag, "secondData"){
    def symbol = column[String]("symbol")
    def date = column[Timestamp]("date")
    def secondField= column[String]("secondField")
    def * = (symbol, date, secondField) <> ((SecondData.apply _).tupled, SecondData.unapply)
    def pk = primaryKey("pk_secondData", (symbol, date))
}

最后TableQuery个类是:

val firstDataTableQuery = TableQuery[FirstDataTable]
val secondDataTableQuery = TableQuery[SecondDataTable]
etc ...

如何制作一个通用的Slick过滤器查询函数,该函数将firstDataTableQuerysecondDataTableQuery作为参数并对输入进行相同的光滑查询。仅在其公共字段上过滤或以其他方式过滤在其SQL表表示公共列上。例如:

def filter(genericTableQuery: TableQuery) = {
    genericTableQuery.filter { data => dataFilterFunction(data.symbol)
    }.filter(_.date >= someDate).sortBy(data => data.date.asc)
}

val firstTableResult = filter(firstDataTableQuery)
val seconfTableResult = filter(secondDataTableQuery)
etc ...

我查看了这个主题,但仍无法解决问题:

Slick 3 reusable generic repository

Scala reflection to instantiate scala.slick.lifted.TableQuery

2 个答案:

答案 0 :(得分:0)

如何使数据表类扩展一个共同特征,这反过来又扩展了数据类的共同特征,例如:

trait Data {
  def symbol: String
  def date: Timestamp
}
// make FirstData and SecondData extend the above trait

trait GenericDataTable extends Data {
  def symbol: Rep[String]
  def date: Rep[Timestamp]
  def pk: PrimaryKey
}


class FirstDataTable(tag: Tag) extends Table[FirstData](tag, "firstData") with GenericDataTable {
// ...

然后:

def filter[T <: GenericDataTable](genericTableQuery: TableQuery[T]) = // ...

答案 1 :(得分:0)

invariant,非常感谢。你指出了正确的方向。我稍微修改了你的答案,一切正常)

性状:

trait Data {
            def symbol: String
            def date: Timestamp
            }

trait GenericDataTable[T <: Data] extends Table[T] {
            def symbol: Rep[String]
            def date: Rep[Timestamp]
            def pk: PrimaryKey
            }

FirstData和FirstDataTable类如下所示:

case class FirstData(
            symbol: String,
            date: Timestamp,
            firstField: Double) extends Data

class FirstDataTable(tag: Tag) extends Table[FirstData(tag,"firstData") 
    with GenericDataTable[FirstData] {
            def symbol = column[String]("symbol")
            def date = column[Timestamp]("date")
            def firstField= column[Double]("firstField")
            def * = (symbol, date, firstField) <> ((FirstData.apply _).tupled, FirstData.unapply)
            def pk = primaryKey("pk_firstData", (symbol, date))
    }

最后功能如下:

private def filter[M <: Data, T <: GenericDataTable[M]] (genericTableQuery: TableQuery[T]) = {
            genericTableQuery.filter { data => dataFilterFunction(data.symbol)}.
            filter(_.date >= someDate).sortBy(data => data.date.asc)
    }