我正在使用Scala、Scalatra和Squeryl进行我的第一个实质性项目,并且遇到了以下问题:我想为我的DAOs创建一个抽象基类,它提供了一个基本CRUD操作的简单实现(创建、读取、更新、删除),所以我需要一种方法,让这个抽象基类知道要引用哪个表。
使用Squeryl,您可以将数据类映射到扩展squeryl.Schema的单例对象中的实际表,而DAO通常是每个类的伴生对象。
我想出了以下使用类型标记的解决方案:
首先,摘录所有DAO将继承的基类(注意: DBRecord是Squeryl's KeyedEntity的一个子类):
abstract class CrudOps[S <: DBRecord](implicit tt: TypeTag[S]) {
def create(item: S)= {
inTransaction{
val result = ATSchema.recordTable.insert(item)
}
}接下来,在recordTable中使用ATSchema函数:
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()中的表放到TableT中呢?如果删除.asInstanceOf,则会得到类型不匹配,但用户的类型是TableUser.看来这应该是不必要的。而且,对于应该是一个小问题(也许我在滥用类型系统)来说,这是一个复杂的解决方案,并且将CrudOps耦合到模式(我想避免这种情况),所以我当然愿意接受那些比我有更多Scala和/或Squeryl经验的人的建议。
发布于 2013-09-06 12:51:11
这不是斯奎里尔的事。据我了解,问题是模式匹配测试是在类型擦除发生后在运行时进行的。Scala能够在TypeTag中保留类型信息并执行运行时检查,但它不能推断类型在编译时是正确的。如果你想尝试一下
case t: ClassTag[User] => users它要求编译器执行静态检查,您将得到用户类型被删除的警告。您所做的方式应该有效,因为在您验证了类型之后执行强制转换应该很好,而且我认为没有更好的方法。
https://stackoverflow.com/questions/18407145
复制相似问题