如何在ScalaQuery中撰写查询以创建可重用的特征?

时间:2012-06-03 23:34:18

标签: scala scalaquery

我在将不同的查询组件组合到一个查询中时遇到了一些麻烦。我的目标是创建一组特征(例如SoftDeletable,HasName,SortedByName,WithTimestamps),我可以简单地将它们混合到Table对象中以添加该行为。

理想情况如下:

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做这些事吗?主要的关键点是:

  1. 如何在SoftDeletable.allQuery中清晰地构成过滤器,在SortedByName.allQuery中使用BaseModel.allQuery进行排序?

  2. 通过在*方法的子类实现中添加列,Table的元组类型参数没有后者匹配 - 这些特征是否有一种方法可以逐步向列添加新类型最终具体课堂中的元组? (我不指望会有,但如果有一些我缺少的东西会很好。)

  3. 我需要在每个特征中重复长元组声明,如果一个表有五列或六列,这将变得非常笨重。我可以对类型成员做些什么来避免做以下事情:

    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)] {
    }
    
  4. 我可以避免所有这些重复吗?基于jesnor对IRC的建议,我能够避免这样的一些事情:

    abstract class SoftDeletableBaseModel[TupleClass <: Product, CaseClass](tableName: String)
            extends BaseModel[TupleClass, CaseClass](tableName)
            with SoftDeletable[TupleClass,CaseClass]
    

    换句话说,通过将特定特征组合在一起,我不需要重复整个元组声明;当然,缺点是不再可能容易混入各种特征 - 我需要创建许多特定的子类来避免这种重复。还有另一种方式吗?

    更新:所以我意识到我不需要使用单独的CaseClass和TupleClass类型参数。由于案例类实现了Product*,你可以将案例类名称传递给Table,这解决了3中的问题:

    trait SoftDeletable[CaseClass] extends BaseModel[CaseClass] { ... }
    
    class Models extends BaseModel[Model]("models") with SoftDeletable[Model] { ... }
    

1 个答案:

答案 0 :(得分:1)

如果你的问题只是添加排序,那不仅仅是flatMap的问题吗?

def sortBy[T,U,C](q: Query[T,U], col: NamedColumn[C]) = q.flatMap(_ => Query orderBy col)