4

我已经使用 Spring 和 Jetty 创建了一个简单的 webapp,并且正在使用 DataNucleus 和 DB4O 创建一个 hello world JDO 测试。

我可以坚持上课没问题,但是当我去查询课程时,我得到了一个ClassCastException,不能a.b.c.MyClass转换为a.b.c.MyClass.

当我检查我创建的原始对象的类加载器时,它[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 中的以下调试步骤验证了类加载器WebAppClassLoader在 Servlet 中:

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

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

我不确定我要去哪里错了。

4

1 回答 1

1

我之前的评论作为答案:

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

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 的实例而不是类加载器。在那里你可以实现任何类查找方法。例如在多个类加载器中查找。

于 2010-10-25T16:40:28.880 回答