我开始使用后端使用Hibernate(JPA)的Scala应用程序。为了加载一个对象,我使用这行代码:
val addr = s.load(classOf[Address], addr_id).asInstanceOf[Address];
毋庸置疑,这有点痛苦。我写了一个帮助类,看起来像这样:
import org.hibernate.Session
class DataLoader(s: Session) {
def loadAddress(id: Long): Address = {
return s.load(classOf[Address], id).asInstanceOf[Address];
}
...
}
所以,现在我可以这样做:
val dl = new DataLoader(s)
val addr = dl loadAddress(addr_id)
以下是问题:如何编写可以使用相同模式加载任何对象的通用参数化方法?即
val addr = dl load[Address](addr_id)
(或沿着这些方向的东西。)
我是Scala的新手所以请原谅任何特别可怕的东西。
答案 0 :(得分:5)
这是:
import org.hibernate.Session
class DataLoader(s: Session) {
def load[A](id: Long)(implicit m: Manifest[A]): A = {
return s.load(m.erasure, id).asInstanceOf[A];
}
}
编辑 - 或者,确保任何播放错误 - 由于hibernate返回错误的对象 - 将在load
内发生,如下所示:
import org.hibernate.Session
class DataLoader(s: Session) {
def load[A](id: Long)(implicit m: Manifest[A]): A = {
return m.erasure.asInstanceOf[Class[A]].cast(s.load(m.erasure, id));
}
}
在Scala 2.8上你也可以这样写:
import org.hibernate.Session
class DataLoader(s: Session) {
def load[A : Manifest](id: Long): A = {
return s.load(manifest[A].erasure, id).asInstanceOf[A];
}
}
您也可以将其与隐式会话结合使用,如Chris所示:
def load[A](id: Long)(implicit m: Manifest[A], s: org.hibernate.Session): A = {
return s.load(m.erasure, id).asInstanceOf[A];
}
请注意,您无法将上下文视图表示法(A : Manifest
)与其他隐式参数组合使用。
答案 1 :(得分:3)
一种方法是利用java.lang.Class.cast
方法来执行以下操作:
def load[A](clazz: Class[A], id: Long)(implicit s: Session) : A
= clazz.cast(s.load(clazz, id))
然后用法如下:
implicit val s = ...//get hibernate session
val addr = load(classOf[Address], 1)
它与你已经没有什么不同,但为了访问class
实例,你需要传入它。
我非常有信心你不能安全用Manifests
做你想做的事情,因为他们无法在编译时提供参数化Class[Address]
为了使演员工作所需的时间(他们只能提供Class[_]
的删除)。我没有看到任何其他机制来从Manifest
您当然可以使用asInstanceOf[A]
而不是cast
,但这会在编译时被删除到isInstanceOf[Object]
,因此在编译时类型检查方面无用(因此不可取) )。