Исключение Hibernate Serialization в GWT, но Eclipselink нет - PullRequest
3 голосов
/ 03 августа 2010

Я использую реализацию eclipselink JPA (Entity) с платформой GWT 2.0 на уровне представления.Все работает правильно.Но когда я изменяю свою реализацию JPA на Hibernate, я получаю исключение сериализации / десериализации на уровне GWT, когда я передаю бины сущностей, но это нормально для eclipselink JPA.Что на самом деле происходит?Hibernate - это реализация JPA и eclipselink, почему они действуют по-разному?

Что я должен сделать для решения этого исключения в Hibernate?использование Hibernate4gwt?

Какая реализация JPA лучше для GWT?

С уважением

Ответы [ 2 ]

7 голосов
/ 03 августа 2010

Я рекомендую прочитать все Используя GWT с бумагой Hibernate , это очень хорошо объясняет, почему расширенные классы (независимо от того, используете ли вы прокси или ткачество) являются "проблемными" для GWT:

Почему объекты Hibernate не могут быть поняты, когда они достигают мира браузера

...

Когда вы берете объект и превращаете его в Hibernateобъект, объект теперь улучшен, чтобы быть постоянным .Эта настойчивость не приходит без какого-либо инструментария объекта.В случае Hibernate библиотека Javassist фактически заменяет и переписывает байт-код для этих объектов постоянными объектами, чтобы заставить магию Hibernate работать. Что это означает для GWT RPC, так это то, что к тому моменту, когда объект готов к передаче по проводам, он на самом деле уже не тот объект, который, как думал компилятор, должен был быть передан, поэтому при попытке десериализацииМеханизм GWT RPC больше не знает, что такое тип, и отказывается десериализовать его .

На самом деле, если бы вы заглянули глубже к более раннему вызову loadAccounts() и вступили в RPC.invokeAndEncodeResponse()метод, вы увидите, что объект, который мы пытаемся десериализовать, теперь стал ArrayList типами учетных записей с их java.util.Set записями, замененными типом org.hibernate.collection.PersistentSet.

аналогичные проблемывозникают с другими средами персистентности, такими как JDO или JPA , используемыми в Google App Engine.

...

Так что я понимаю, что это не Hibernateспецифическая проблема, и вы также можете столкнуться с проблемами с альтернативными реализациями JPA, включая EclipseLink , если вы используете статическое или динамическое плетение (вы не обязаныo использовать ткачество, но тогда вы упускаете такие функции, как отложенная загрузка или выборка групп).

В документе предлагается несколько стратегий интеграции, позволяющих обойти проблемы:

  • Использование объектов передачи данных (argh!)
  • Использование Dozer для интеграции Hibernate (улучшенная версия предыдущего подхода)
  • Использование Gilead (ранее известный как Hibernate4Gwt) для Hibernate Integration

Здесь также обсуждаются их плюсы и минусы, просто проверьте его.

Подводя итог ...

Во-первых, я не думаю, что есть "лучшая" реализация JPA для GWT, все они сталкиваются с одной и той же проблемой.Если вы можете жить без ленивой загрузки, EclipseLink без ткачества может быть проще.Но вы бы как-то уткнулись головой в песок, проблема там , и вы не сможете использовать другую реализацию.

Во-вторых, хотя две первые «стратегии интеграции» будут работать с любым провайдером JPA, Hibernate является единственной реализацией JPA, в настоящее время поддерживаемой Gilead (но планируется Поддержка OpenJPA и EclipseLink ).

Выберите яд:)

См. Также

0 голосов
/ 14 октября 2011

Еще одна мысль: настраиваемые полевые сериализаторы.

Пример: MyClass имеет члена, сопоставленного в отношениях «Один ко многим» с YourClass:

public class MyClass implements Serializable {

    private List<YourClass> yourClassList;

    @OneToMany(mappedBy="myClass")
    public List<YourClass> getYourClassList {
        return yourClassList;
    }
}

Точной реализацией, которую будет использовать Hibernate, является, вероятно, PersistentBag, который не сериализуем по причинам, упомянутым Паскалем. Но GWT предоставляет настраиваемые полевые сериализаторы для управления сериализацией. Это будет выглядеть примерно так.

public class MyClass_CustomFieldSerializer {
   public serialize(SerializationStreamWriter writer, MyClass instance) throws SerializationException {
       writer.write(new ArrayList<YourClass>(instance.getYourClassList());
   }
}

Преимущество здесь в том, что вам не нужно связываться с Gilead / Dozer / другими внешними библиотеками.

...