scala 的通用对象加载函数

发布于 2024-08-24 17:44:35 字数 684 浏览 5 评论 0原文

我开始开发一个在后端使用 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 的新手,所以请原谅这里特别可怕的任何内容。

I'm starting on a Scala application which uses Hibernate (JPA) on the back end. In order to load an object, I use this line of code:

val addr = s.load(classOf[Address], addr_id).asInstanceOf[Address];

Needless to say, that's a little painful. I wrote a helper class which looks like this:

import org.hibernate.Session

class DataLoader(s: Session) {
  def loadAddress(id: Long): Address = {
    return s.load(classOf[Address], id).asInstanceOf[Address];
  }
  ...
}

So, now I can do this:

val dl = new DataLoader(s)
val addr = dl loadAddress(addr_id)

Here's the question: How do I write a generic parametrized method which can load any object using this same pattern? i.e

val addr = dl load[Address](addr_id)

(or something along those lines.)

I'm new to Scala so please forgive anything here that's especially hideous.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

飘过的浮云 2024-08-31 17:44:35

这里是:

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];
  }
}

编辑 - 或者,为了确保任何转换错误 - 由于休眠返回错误的对象 - 都会在 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) 与其他隐式参数结合起来。

Here it is:

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];
  }
}

EDIT -- Or, to ensure that any casting error -- as a result of hibernate returning the wrong object -- will happen inside load, like this:

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));
  }
}

On Scala 2.8 you can also write it like this:

import org.hibernate.Session
class DataLoader(s: Session) {
  def load[A : Manifest](id: Long): A = {
    return s.load(manifest[A].erasure, id).asInstanceOf[A];
  }
}

You can combine it with an implicit session as well, as suggested by Chris:

def load[A](id: Long)(implicit m: Manifest[A], s: org.hibernate.Session): A = {
  return s.load(m.erasure, id).asInstanceOf[A];
}

Note that you can't combine context view notation (A : Manifest) with additional implicit parameters.

骄傲 2024-08-31 17:44:35

一种方法是利用 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 实例,您需要将其传入。

我非常有信心您无法安全地使用 做您想做的事情 code>Manifests 因为它们无法在编译时提供您需要的参数化 Class[Address] 以便强制转换工作(它们只能提供擦除) em> Class[_])。我没有看到任何其他机制可以从 Manifest 进行强制转换,

您当然可以使用 asInstanceOf[A] 而不是 cast 但这在编译时被删除为 isInstanceOf[Object],因此在编译时类型检查方面毫无用处(因此不建议)。

One method would be to do take advantage of the java.lang.Class.cast method in order to do something like:

def load[A](clazz: Class[A], id: Long)(implicit s: Session) : A 
       = clazz.cast(s.load(clazz, id))

Then the usage is as follows:

implicit val s = ...//get hibernate session
val addr = load(classOf[Address], 1)

It's not hugely different from what you have already but in order to access the class instance, you need to pass it in.

I'm pretty confident that you cannot safely do what you want with Manifests because they cannot supply the parametrized Class[Address] at compile-time which you need in order for the cast to work (they can only supply the erasure of Class[_]). I don't see any other mechanism for doing a cast from a Manifest

You can of course use asInstanceOf[A] instead of cast but this gets erased at compile-time to isInstanceOf[Object] and is therefore useless in terms of compile-time type checking (and hence unadvisable).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文