Один фильтр Scala Slick для нескольких экземпляров TableQuery
Я использую Scala Slick-3.1.0 lib.
Как можно сделать универсальную функцию фильтра Slick, которая принимает экземпляр TableQuery в качестве входного и делает такой же фильтр Slick на нем?
У меня есть несколько классов дел (например, два), представляющих данные, хранящиеся в БД. Некоторые поля одинаковы, поэтому классы могут расширять общего предка:
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
в качестве аргумента и делает такой же ловкий запрос на входе. Фильтрация только по их общим полям или иначе говоря, по их представлениям таблицы 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
2 ответа
maciekjanusz, спасибо большое. Вы указали мне в правильном направлении. Я слегка модифицировал ваш ответ и все работает)
Черты:
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)
}
Как насчет того, чтобы заставить классы таблиц данных расширять общую черту, которая, в свою очередь, расширяет общую черту для классов данных, например:
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]) = // ...