Как я могу составлять запросы в ScalaQuery для создания черт многократного использования?
У меня возникли проблемы при объединении различных компонентов запроса в один запрос. Моя цель - создать набор характеристик (например, SoftDeletable, HasName, SortedByName, WithTimestamps), которые я могу просто добавить к объектам таблицы, чтобы добавить это поведение.
Идеал будет выглядеть так:
abstract class BaseModel[Tuple <: Product,CaseClass](tableName: String)
extends Table[Tuple](tableName) {
def id = column[Int]("id", O.AutoInc, O.PrimaryKey)
def mapped: MappedProjection[CaseClass, TupleClass]
def allQuery = this.map(_.mapped)
final def all = database.withSession { implicit session: Session =>
allQuery.list()
}
...
}
trait SoftDeletable[Tuple <: Product, CaseClass]
extends BaseModel[Tuple,CaseClass] {
def isActive = column[String]("is_active")
def * = super.* ~ isActive
def allQuery = /* here, I'd like to compose super.allQuery
with a filter that returns rows where isActive is true */
}
trait HasName[Tuple <: Product] extends Table[Tuple] {
def name = column[String]("name")
def * = super.* ~ name
}
trait SortedByName[Tuple <: Product] extends HasName[Tuple {
override def allQuery = super.allQuery /* compose somehow
with (_ <- Query orderBy name */
}
Могу ли я делать такие вещи с ScalaQuery? Основные точки преткновения:
Как правильно составить фильтры в
SoftDeletable.allQuery
и сортировать вSortedByName.allQuery
сBaseModel.allQuery
?Добавляя столбцы в реализации подкласса
*
метод, параметр типа кортежа дляTable
нет последних совпадений - есть ли способ для этих признаков постепенно добавлять новые типы в кортеж столбцов в конечном конкретном классе? (Я не ожидаю, что будет, но было бы хорошо, если бы я что-то упустил).Мне нужно повторять длинное объявление кортежа в каждой черте, которое становится очень громоздким, если в таблице пять или шесть столбцов. Есть ли что-то, что я могу сделать с членами типа, чтобы избежать таких вещей, как:
case class Foo class Foos[(Int,Int,Boolean,String), Foo] extends Table[(Int,Int,Boolean,String)] with SoftDeletable[(Int,Int,Boolean,String), Foo] with SortedByName[(Int,Int,Boolean,String), Foo] with HasName[(Int,Int,Boolean,String)] { }
Могу ли я избежать всего этого повторения? Основываясь на предложении jesnor о IRC, я смог избежать некоторых из них, например, так:
abstract class SoftDeletableBaseModel[TupleClass <: Product, CaseClass](tableName: String)
extends BaseModel[TupleClass, CaseClass](tableName)
with SoftDeletable[TupleClass,CaseClass]
Другими словами, объединяя определенные черты вместе, мне не нужно повторять всю декларацию кортежа; Конечно, недостатком является то, что простое смешивание различных признаков больше невозможно - мне нужно создать множество определенных подклассов, чтобы избежать этого повторения. Есть ли другой способ?
Обновление: поэтому я понял, что мне не нужно использовать отдельные параметры типа CaseClass и TupleClass. Так как тематические классы реализуют Product*
, вы можете просто передать имя класса case в Table, что решает проблему в 3:
trait SoftDeletable[CaseClass] extends BaseModel[CaseClass] { ... }
class Models extends BaseModel[Model]("models") with SoftDeletable[Model] { ... }
1 ответ
Если ваша проблема заключается только в добавлении сортировки, разве это не вопрос плоской карты?
def sortBy[T,U,C](q: Query[T,U], col: NamedColumn[C]) = q.flatMap(_ => Query orderBy col)