ClassCastException в объекте DAO DataNucleus при сохранении / извлечении объекта с использованием JDO - PullRequest
4 голосов
/ 25 октября 2010

Я создал простое веб-приложение, используя Spring & Jetty, и создаю тест JDO hello world с использованием DataNucleus & DB4O.

Я могу сохранить класс без проблем, но когда я иду, чтобы запросить класс, я получаю ClassCastException, не могу привести a.b.c.MyClass к a.b.c.MyClass.

Когда я проверяю загрузчик классов исходного объекта, который я создал, он [WebAppClassLoader@1592226291], естественно, это источник загрузчика классов WebApp.

Я выполняю как операцию постоянства, так и операцию запроса в одном и том же методе сервлета, когда я перечитываю объект из БД простым запросом, я получаю набор объектов abcMyClass из БД, но загрузчик классов [sun.misc.Launcher$AppClassLoader@5acac268], следовательно, исключение.

В соответствии с документами DataNucleus здесь http://www.datanucleus.org/extensions/classloader_resolver.html

... механизм загрузки классов JDO2 использует 3 класса погрузчиков
* При создании PersistenceManagerFactory вы можете указать загрузчик классов. Это используется сначала, если указано
* Загрузчик второго класса, который нужно попробовать, является загрузчиком класса для текущего нить.
* Загрузчик третьего класса - загрузчик классов для контекста PMF.

Я рассмотрел первые две задокументированные опции и убедился, что загрузчик классов является WebAppClassLoader в сервлете, выполнив следующие шаги отладки в сервлете:

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

Оба выдают [WebAppClassLoader@1592226291] в качестве загрузчика классов.

Я не уверен, куда я иду не так.

1 Ответ

1 голос
/ 25 октября 2010

Мой предыдущий комментарий в качестве ответа:

Это исключение указывает, что это проблема загрузчика классов. Сравните загрузчик классов объекта и класс, который вы используете для приведения.

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 вместо загрузчика классов. Там вы можете реализовать любой метод поиска классов. Например, для поиска в нескольких загрузчиках классов.

...