Scala反射和Squeryl [英] Scala reflection and Squeryl

查看:74
本文介绍了Scala反射和Squeryl的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm working on my first substantial project using Scala, Scalatra, and Squeryl, and happened upon the following problem: I wanted to have an abstract base class for my DAOs that provided a simple implementation of the basic CRUD operations (create, read, update, delete), so I needed a way for said abstract base class to be aware of which table to reference.

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

With Squeryl, you map your data classes to actual tables in a singleton object that extends squeryl.Schema, and your DAOs are generally companion objects for each class.

我想出了使用类型标签的以下解决方案:

I came up with the following solution using type tags:

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

First, an excerpt of the base class from which all DAOs will inherit (Note: DBRecord is a sub of Squeryl's KeyedEntity):

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

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

接下来,ATSchema中的recordTable函数:

Next, the recordTable function in 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()中的表vals强制转换为Table [T]?如果删除.asInstanceOf,则会出现类型不匹配的情况,但用户的类型为Table [User] ...似乎应该没有必要.另外,这对于应该是一个小问题(也许我正在滥用类型系统)有一个复杂的解决方案,并且还将CrudOps与Schema耦合(我想避免),所以我当然愿意接受比我有更多Scala和/或Squeryl经验的人的建议:)

Now, this works, I have several tables and CrudOps grabs the right one and does its stuff. But there's something I'm not understanding (I'm still fairly new to Scala): Why do I need to cast my table vals in recordTable() to Table[T]? If I remove the .asInstanceOf, I get a type mismatch, but users is of the type Table[User]... seems like it ought to be unnecessary. Also, this has the feel of a complicated solution to what should be a trivial problem (maybe I'm abusing the type system), and also couples CrudOps to the Schema (which I would like to avoid), so I am certainly open to suggestions from folks with more Scala and/or Squeryl experience than I :)

推荐答案

这并不是Squeryl真正的东西.据我了解,问题在于模式匹配测试是在类型擦除发生后在运行时完成的. Scala能够将类型信息与TypeTag保持在一起并执行运行时检查,但是它不能推断在编译时类型是否正确.如果您要尝试类似

It's not really a Squeryl thing. As I understand it, the problem is that the pattern match testing is done at runtime, after type erasure has occurred. Scala is able to keep the type information around with the TypeTag and perform the runtime check but it can't infer that the types are correct at compile time. If you were to try something like

case t: ClassTag[User] => users

要求编译器进行静态检查,您将得到一条警告,提示用户类型已删除.您的操作方式应该可以正常工作,因为在验证类型之后,可以很好地执行转换,而且我认为没有更好的方法.

Which is asking the compiler to do a static check, you would get a warning that the User type is erased. The way you are doing it should work since it should be fine to perform the cast after you've verified the type, and I don't think there is a better way.

这篇关于Scala反射和Squeryl的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆