我在将不同的查询组件组合成一个查询时遇到了一些麻烦。我的目标是创建一组特征(例如 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 做这些事情吗?主要的难点是:
我如何干净地组合过滤器和
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 类型参数。既然case类实现Product*
了,就可以把case类名传给Table,解决了3中的问题:
trait SoftDeletable[CaseClass] extends BaseModel[CaseClass] { ... }
class Models extends BaseModel[Model]("models") with SoftDeletable[Model] { ... }