Одиночный фильтр Scala Slick для нескольких экземпляров TableQuery

Я использую библиотеку Scala Slick-3.1.0.

Как можно создать общую функцию фильтра Slick, которая принимает экземпляр TableQuery в качестве входных данных и создает для него такой же фильтр Slick?

У меня есть несколько классов case (например, два), представляющих данные, хранящиеся в БД. Некоторые поля одинаковы, поэтому классы могут расширять общего предка:

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

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

Каждый из них имеет свою 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, которая принимает firstDataTableQuery или secondDataTableQuery в качестве аргумента и делает такой же запрос slick на входе. Фильтрация только по их общим полям или, другими словами, по общим столбцам их представлений в таблице 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 для повторного использования

Отражение Scala для создания экземпляра scala.slick.lifted.TableQuery< /а>


person aaamarkin    schedule 12.01.2016    source источник


Ответы (2)


Как насчет того, чтобы классы таблиц данных расширяли общую черту, которая, в свою очередь, расширяла общую черту для классов данных, например:

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]) = // ...
person maciekjanusz    schedule 12.01.2016

инвариант, большое спасибо. Вы указали мне правильное направление. Я немного изменил ваш ответ, и все работает)

Черты:

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)
    }
person aaamarkin    schedule 13.01.2016