Scala反射和Squeryl

时间:2013-08-23 16:00:00

标签: scala squeryl

我正在使用Scala,Scalatra和Squeryl开展我的第一个实质性项目,并遇到了以下问题: 我希望为我的DAO提供一个抽象基类,它提供了基本CRUD操作(创建,读取,更新,删除)的简单实现,因此我需要一种方法让所述抽象基类知道要引用哪个表。

使用Squeryl,您可以将数据类映射到扩展squeryl.Schema的单个对象中的实际表,并且您的DAO通常是每个类的伴随对象。

我使用类型标记提出了以下解决方案:

首先,所有DAO将从中继承的基类的摘录(注意:DBRecord是Squeryl的KeyedEntity的子类):

abstract class CrudOps[S <: DBRecord](implicit tt: TypeTag[S]) {

  def create(item: S)= {
    inTransaction{
      val result = ATSchema.recordTable.insert(item)
    }
  }

接下来,ATSchema中的recordTable函数:

object ATSchema extends Schema {
  val users = table[User]
  def recordTable[T <: DBRecord](implicit tt: TypeTag[T]): Table[T] = tt.tpe match {
    case t if t =:= typeOf[User] => users.asInstanceOf[Table[T]]
    //...other table types go here
    case _ => throw new IllegalArgumentException("Unknown DBRecord type")
  }
}

现在,这个工作,我有几个表,CrudOps抓住正确的一个并完成它的东西。但是有一些我不理解的东西(我仍然是Scala的新手):为什么我需要将recordTable()中的表格值转换为Table [T]?如果我删除.asInstanceOf,我得到一个类型不匹配,但用户类型为Table [User] ...似乎它应该是不必要的。此外,这有一个复杂的解决方案的感觉应该是一个小问题(也许我滥用类型系统),并将CrudOps耦合到Schema(我想避免),所以我当然愿意人们的建议比我更多Scala和/或Squeryl经验。

1 个答案:

答案 0 :(得分:2)

这不是真正的Squeryl事。据我了解,问题是模式匹配测试是在发生类型擦除后在运行时完成的。 Scala能够使用TypeTag保留类型信息并执行运行时检查,但它无法在编译时推断出类型是正确的。如果您尝试类似

的话
case t: ClassTag[User] => users

这是要求编译器进行静态检查,您会收到一条警告,即用户类型已被删除。你这样做的方式应该有效,因为在你验证了类型后执行演员应该没问题,我认为没有更好的方法。