使用 JDO 持久化/检索对象时 DataNucleus DAO 对象中出现 ClassCastException

发布于 2024-09-28 18:53:23 字数 1229 浏览 3 评论 0原文

我使用 Spring & 创建了一个简单的网络应用程序。 Jetty,并且正在使用 DataNucleus 和 JDO 创建一个 hello world JDO 测试。 DB4O。

我可以毫无问题地保留一个类,但是当我去查询该类时,我得到一个 ClassCastException,无法将 abcMyClass 转换为 abcMyClass

当我检查我创建的原始对象的类加载器时,它是[WebAppClassLoader@1592226291],自然是springs WebApp类加载器。

我在同一个 servlet 方法中执行持久操作和查询操作,当我使用简单查询从数据库重新读取对象时,我从数据库返回一组 abcMyClass 对象,但类加载器是 [ sun.misc.Launcher$AppClassLoader@5acac268],因此出现异常。

按照此处的 DataNucleus 文档 http://www.datanucleus.org/extensions/classloader_resolver.html

...JDO2 类加载机制 使用 3 个类加载器
* 创建PersistenceManagerFactory时你可以 指定一个类加载器。这是用的 如果指定的话首先
* 要尝试的第二个类加载器是当前的类加载器 线程。
* 要尝试的第三个类加载器是 PMF 上下文的类加载器。

我介绍了记录的前两个选项,并通过 servlet 中的这些调试步骤验证了类加载器是 Servlet 中的 WebAppClassLoader

Thread.currentThread().getContextClassLoader().toString()
((JDOPersistenceManagerFactory)pm.getPersistenceManagerFactory()).getPrimaryClassLoader().toString()

两者均产生 [WebAppClassLoader@1592226291] 作为类加载器。

我不确定我哪里错了。

I've created a simple webapp using Spring & Jetty, and am creating a hello world JDO test using DataNucleus & DB4O.

I can persist a class no problem, but when I go to query for the class I get a ClassCastException, can't cast a.b.c.MyClass to a.b.c.MyClass.

When I examine the classloader of the original object I created, it's [WebAppClassLoader@1592226291], naturally it's springs WebApp classloader.

I am performing both the persist operation and query operation in the same servlet method, when I re-read the object from the DB with a simple query I get back a set of a.b.c.MyClass objects from the DB, but the classloader is [sun.misc.Launcher$AppClassLoader@5acac268], thus the exception.

Following the DataNucleus docs here http://www.datanucleus.org/extensions/classloader_resolver.html

...the JDO2 class-loading mechanism
utilises 3 class loaders

* When creating the PersistenceManagerFactory you can
specify a class loader. This is used
first if specified
* The second class loader to try is the class loader for the current
thread.
* The third class loader to try is the class loader for the PMF context.

I covered the first two options documented, and verified that the classloader is the WebAppClassLoader in the Servlet with these debug steps in the servlet:

Thread.currentThread().getContextClassLoader().toString()
((JDOPersistenceManagerFactory)pm.getPersistenceManagerFactory()).getPrimaryClassLoader().toString()

Both yield [WebAppClassLoader@1592226291] as the classloader.

I'm not sure where I'm going wrong here.

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

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

发布评论

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

评论(1

不念旧人 2024-10-05 18:53:23

我之前的评论作为答案:

此异常表明它是一个类加载器问题。比较对象的类加载器和用于转换的类。

ClassLoader loaderOfObject = theObject.getClass().getClassLoader();
ClassLoader loaderOfLocalClass = MyClass.getClassLoader();
// have to be the same.
assert loaderOfObject.equals(loaderOfLocalClass);

顺便说一句:如果 db4o 使用了错误的类加载器。您可以通过显式配置类加载器来更改它。

    EmbeddedConfiguration configuration = Db4oEmbedded.newConfiguration();
    JdkReflector reflector = new JdkReflector(Thread.currentThread().getContextClassLoader());
    configuration.common().reflectWith(reflector);
    ObjectContainer container = Db4oEmbedded.openFile(configuration, "database.db4o");

当单个类加载器不够时:您还可以传递 db4o 接口 JdkLoader 的实例而不是类加载器。在那里你可以实现任何类查找方法。例如,在多个类加载器中查找。

My earlier comment as an answer:

This exception indicates that it is a class loader issue. Compare the class-loader of the object and the class you're using for the cast.

ClassLoader loaderOfObject = theObject.getClass().getClassLoader();
ClassLoader loaderOfLocalClass = MyClass.getClassLoader();
// have to be the same.
assert loaderOfObject.equals(loaderOfLocalClass);

Btw: If db4o is using the wrong class-loader. You can change that by configuring the class-loader explicit.

    EmbeddedConfiguration configuration = Db4oEmbedded.newConfiguration();
    JdkReflector reflector = new JdkReflector(Thread.currentThread().getContextClassLoader());
    configuration.common().reflectWith(reflector);
    ObjectContainer container = Db4oEmbedded.openFile(configuration, "database.db4o");

When a single class-loader isn't enough: You can also pass a instance of the db4o-interface JdkLoader instead of a class-loader. In there you can implement any class-lookup method. For example to look up in multiple class loaders.

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