Когда и почему сущности JPA должны реализовывать интерфейс Serializable?

151

Вопрос в заголовке. Ниже я только что описал некоторые свои мысли и выводы.

Когда у меня была очень простая модель предметной области (3 таблицы без каких-либо отношений), все мои объекты НЕ реализовывали Serializable.

Но когда модель предметной области стала более сложной, я получил RuntimeException, в котором говорилось, что одна из моих сущностей не реализовала Serializable.

Я использую Hibernate в качестве реализации JPA.

Я думаю:

  1. Это специфичное для поставщика требование / поведение?
  2. Что происходит с моими сериализуемыми объектами? Должны ли они быть сериализуемыми для хранения или передачи?
  3. В какой момент становится необходимым сделать сериализованную мою сущность?
Римский
источник

Ответы:

59

Обычно это происходит, если вы смешиваете HQL и нативные SQL-запросы. В HQL Hibernate сопоставляет передаваемые вами типы с тем, что понимает БД. Когда вы запускаете собственный SQL, тогда вы должны сделать отображение самостоятельно. Если вы этого не сделаете, то по умолчанию сопоставление заключается в сериализации параметра и отправке его в базу данных (в надежде, что он это понимает).

Аарон Дигулла
источник
Это не объясняет, почему просто «возможно, как». См. Ответ ниже от Божо
крипс
это означает, что сущность будет сохранена в БД без реализации сериализуемого интерфейса?
Hanumantha_3048092
@ Hanumantha_3048092 Да. Entity Mapping и Serializableдве разные концепции.
Аарон Дигулла
@AaronDigulla Можете ли вы объяснить это с помощью примера или псевдокода.
sdindiver
110

Согласно спецификации JPA:

Если экземпляр сущности должен передаваться по значению как отдельный объект (например, через удаленный интерфейс), класс сущности должен реализовывать интерфейс Serializable.

«JSR 220: Enterprise JavaBeansTM, версия 3.0 API персистентности Java версии 3.0, финальная версия 2 мая 2006 г.»

Конор
источник
14
(+1) смотреть на спецификации всегда плодотворно
Божо
20
Я не понимаю, почему так много голосов. ОП говорит, что это не требовалось, когда модель была проще. Отправка объектов удаленно через сериализацию Java ВСЕГДА требует, чтобы объекты были сериализуемыми, независимо от их сложности. Очевидно, что это не вариант использования ОП.
Робин
Я не совсем уверен в гибернации, но с другими поставщиками JPA есть операции, которые требуют, чтобы поставщик сделал копию объекта (объекта). Serializableможет быть полезным в этом, и в контексте постоянства более последовательным, чем, Cloneableнапример.
JimmyB
Этот ответ - просто информационная свалка и совсем не помогает кому-то понять, почему.
крип
60

Ваши сущности должны быть такими, Serializableесли вам нужно перенести их по проводам (сериализовать их в какое-то другое представление), сохранить их в сеансе http (который, в свою очередь, сериализуется на жесткий диск контейнером сервлета) и т. Д.

Просто ради настойчивости Serializableне нужно, по крайней мере, с Hibernate. Но это лучшая практика, чтобы сделать их Serializable.

Bozho
источник
2
Я не знаю, может быть, мои сущности куда-то переносятся неявно. Я использую hibernate + spring + jsf и Tomcat. Где в этой цепочке может происходить передача?
Роман
@Roman, например, текущий пользователь (который может быть сущностью) и все связанные с ним сущности могут оказаться в сеансе, который, как говорит Божо, может быть сериализован на диск контейнером сервлета.
OrangeDog
Это лучший ответ «почему и когда»! Очистить! Спасибо
крип
13

Согласно документам спящего режима при использовании аннотации @JoinColumn:

У него есть еще один названный параметр referencedColumnName. Этот параметр объявляет столбец в целевом объекте, который будет использоваться для объединения. Обратите внимание, что при использовании referencedColumnNameдля столбца не первичного ключа, связанный класс должен быть Serializable.

Аман Махарджан
источник
8

В дополнение к приятному ответу Конора, который ссылался на спецификации JSR-317. Как правило, проекты EAR состоят из модуля EJB с EJB, предоставляемыми через удаленный интерфейс. В этом одном случае вам нужно сделать сериализованные бины сущностей такими, как они агрегированы в удаленном EJB-компоненте и созданы для передачи по сети.

Военный проект JEE6 без CDI: может содержать EJB lite, поддерживаемый несериализуемыми сущностями JPA.

Военный проект JEE6 с CDI: bean-компоненты, использующие область сеанса, приложения или диалога, должны быть сериализуемыми, но bean-объекты, использующие область запроса, не должны быть сериализуемыми. Таким образом, базовые бины сущности JPA -if any- будут следовать той же семантике.

Sym-Sym
источник
7

Если мы просто говорим о настойчивости, Serializableэто не нужно, но лучше всего создавать сущности Serializable.

Если мы выставляем объекты domain/ entitiesобъекты, непосредственно представленные на уровне представления, вместо использования DTO, то в этом случае нам нужно реализовать Serializable. Эти доменные объекты могут храниться в HTTPSessionцелях кэширования / оптимизации. Http-сессия может быть сериализована или сгруппирована. И это также требуется для передачи данных между JVMэкземплярами.

Когда мы используем DTOдля разделения персистентного уровня и сервисного уровня, маркировка доменных объектов Serializableбудет непродуктивной и нарушит « encapsulation». Тогда это становится анти-паттерном.

Составные идентификаторы

Класс первичного ключа должен быть сериализуемым.

POJO Модели

Если экземпляр сущности должен использоваться удаленно как отдельный объект, класс сущности должен реализовывать Serializableинтерфейс.

Кэш
Кроме того, если вы реализуете clusteredвторой уровень, cacheто ваши сущности должны быть serializable. Идентификатор должен быть Serializableпотому, что это требование JPA, поскольку его identifierможно использовать в качестве ключа для записи в кэш второго уровня.

И когда мы сериализуем сущности, убедитесь, что предоставили явные serialVersionUID с модификатором частного доступа. Потому что, если serializableкласс явно не объявляет a serialVersionUID, тогда среда выполнения сериализации вычислит serialVersionUIDзначение по умолчанию для этого класса на основе различных аспектов класса, как описано в Спецификации сериализации объектов Java (TM). serialVersionUIDВычисления по умолчанию очень чувствительны к деталям класса, которые могут различаться в зависимости от реализаций компилятора, и, следовательно, могут привести к неожиданным InvalidClassExceptionsпоследствиям при десериализации.

Анкур Сингхал
источник
6

Я считаю, что ваша проблема связана с наличием поля сложного типа (класса), которое не аннотировано. В таких случаях обработка по умолчанию будет хранить объект в его сериализованной форме в базе данных (что, вероятно, не то, что вы хотели сделать) Пример:

Class CustomerData {
    int getAge();
    void setAge(int age);
}

@Entity
Class Customer {
  CustomerData getCustomerData();
  void setCustomerData(CustomerData data)
}

В приведенном выше случае CustomerData будет сохранен в поле байтового массива в базе данных в его сериализованной форме.

Авнер Леви
источник
5

Спецификация JPA

В соответствии со спецификацией JPA, объект должен реализовываться Serializableтолько в том случае, если его необходимо передать из одной JVM в другую или если объект используется компонентом сеанса с сохранением состояния, который должен пассивироваться контейнером EJB.

Если экземпляр сущности должен передаваться по значению как отдельный объект (например, через удаленный интерфейс), класс сущности должен реализовывать Serializableинтерфейс.

Hibernate

Hibernate требует только, чтобы атрибуты сущности были Serializable, но не сама сущность.

Однако, реализуя спецификацию JPA, все требования JPA, касающиеся Serializableсущностей, применимы и к Hibernate.

Кот

Согласно документации Tomcat , HttpSessionатрибуты также должны быть Serializable:

Всякий раз, когда Apache Tomcat нормально выключается и перезапускается, или когда запускается перезагрузка приложения, стандартная реализация Manager будет пытаться сериализовать все текущие активные сеансы в файл на диске, расположенный через атрибут pathname. Все такие сохраненные сеансы будут десериализованы и активированы (при условии, что они не истекли в это время), когда перезагрузка приложения будет завершена.

Чтобы успешно восстановить состояние атрибутов сеанса, все такие атрибуты ДОЛЖНЫ реализовывать интерфейс java.io.Serializable.

Таким образом, если объект хранится в HttpSession, он должен реализовать Serializable.

Влад Михалча
источник
4

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

jarnbjo
источник
3

Пожалуйста, обратитесь http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_to, где сказано: «Реализация java.io.Serializable просто необходима для передачи данных через IIOP или JRMP (RMI) между экземплярами JVM. В случае чистого веб-приложения доменные объекты иногда хранятся в HTTPSession для целей кэширования / оптимизации. Http-сессия может быть сериализована (пассивироваться) или кластеризована. В обоих случаях весь контент должен быть сериализуемым.

Арун К
источник
1

удаленное попадание с использованием почтальона или ajax или углового js и т. д. ....., может вызвать цикл повторения с исключением StackOverflow с Джексоном fastxml. Так что лучше использовать сериализатор.

тамильский
источник
1
  1. В какой момент становится необходимым сделать сериализованную мою сущность?

Реализация ehcache с дисковым хранилищем в качестве кэша второго уровня (т. Е. С использованием @Cacheableаннотации на сущности или метода репозитория / службы) требует Serializable, иначе кешу не удастся ( NotSerializableException) записать сущность в дисковый кеш.

Michal
источник
0

Это также ошибка, которая выдается, когда вы передаете неверно введенный идентификатор в качестве второго параметра чему-то вроде em.find () (т.е. передаете сам объект, а не его идентификатор). Я пока не счел необходимым фактически объявлять сущности JPA сериализуемыми - в действительности это не нужно, если вы не используете referencedColumnName, как описано aman.

Amalgovinus
источник
0

когда объекты JPA используются в качестве параметров или возвращаемых значений удаленными операциями EJB

SAR
источник