Коли і чому суб'єкти JPA повинні реалізувати інтерфейс Serializable?


151

Питання в назві. Нижче я лише описав деякі свої думки та висновки.

Коли у мене була дуже проста модель домену (3 таблиці без будь-яких відносин), всі мої сутності НЕ реалізували Serializable.

Але коли доменна модель стала більш складною, я отримав RuntimeException, який сказав, що одна з моїх організацій не реалізує Serializable.

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

Цікаво:

  1. Це вимога / поведінка, пов’язана з продавцем?
  2. Що відбувається з моїми серіалізаційними сутностями? Чи повинні вони бути серіалізаційними для зберігання чи передачі?
  3. У який момент виникає необхідність зробити мою сутність серіалізаційною?

Відповіді:


59

Зазвичай це відбувається, якщо ви змішуєте HQL та нативні запити SQL. У HQL Hibernate відображає типи, які ви передаєте, до того, що розуміє БД. Коли ви запускаєте нативний SQL, ви повинні виконати відображення самостійно. Якщо ви цього не зробите, то за замовчуванням відображення параметра - це серіалізація параметра та надсилання його до бази даних (з надією, що він це зрозуміє).


Це не пояснює, чому просто "можливо, як" Дивіться відповідь нижче від Bozho
chrips

це означає, що середнє об'єкт буде збережено в БД, не реалізуючи інтерфейс, що серіалізується?
Hanumantha_3048092

@ Hanumantha_3048092 Так. Суб'єктне відображення і Serializableце дві різні концепції.
Аарон Дігулла

@AaronDigulla Чи можете ви поясніть це на прикладі чи псевдокодеком.
sdindiver

110

За словами Спеціалізації JPA:

Якщо екземпляр об'єкта повинен передаватися за значенням як відокремлений об'єкт (наприклад, через віддалений інтерфейс), клас сутності повинен реалізувати інтерфейс Serializable.

"JSR 220: Enterprise JavaBeansTM, Версія 3.0 Java Persistent API API версії 3.0, остаточний випуск 2 травня 2006 року"


14
(+1) дивитись на специфікацію завжди плідно
Божо

20
Я не бачу, чому це так багато відгуків. ОП каже, що цього не потрібно було, коли модель була простішою. Відправлення об’єктів дистанційно за допомогою серіалізації Java ВЖЕ вимагає об'єктів бути серіалізаційними, незалежно від їх складності. Очевидно, це не випадок використання ОП.
Робін

Я не зовсім впевнений у сплячому режимі, але з іншими постачальниками JPA є операції, які вимагають від постачальника зробити копію суб'єкта (об'єкта). Serializableможе бути корисним для цього і в контексті наполегливості, більш послідовної, ніж, Cloneableнаприклад,.
JimmyB

Ця відповідь є лише інформаційним сміттям і зовсім не допомагає комусь зрозуміти, чому.
щебетати

59

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

Тільки заради наполегливості, Serializableне потрібна, принаймні, в сплячку. Але це найкраща практика їх виготовлення Serializable.


2
Я не знаю, можливо, мої сутності кудись неявно переносяться. Я використовую сплячку + весна + jsf та Tomcat. Де в цьому ланцюжку може відбуватися передача?
Роман

@Roman, наприклад, поточний користувач (який може бути сутністю) і всі пов'язані з ним об'єкти можуть закінчитися сеансом, який, як говорить Божо, може бути серіалізований на диск контейнером сервлетів.
OrangeDog

ЦЕ найкраща відповідь "чому і коли"! Ясно! Дякую
зажурює

13

Згідно з документами про сплячку , використовуючи анотацію @JoinColumn:

У нього є ще один параметр з назвою referencedColumnName. Цей параметр оголошує стовпець у цільовому об'єкті, який буде використовуватися для з'єднання. Зауважте, що при використанні referencedColumnNameв стовпчику не первинного ключа асоційований клас повинен бути Serializable.


8

Щоб доповнити приємну відповідь Конора, який послався на технічні характеристики JSR-317. Зазвичай проекти EAR складаються з модуля EJB, в якому EJB піддаються впливу віддаленого інтерфейсу. У цьому випадку вам потрібно зробити сеанси своїх об'єктів серіалізаційними, оскільки вони агрегуються у віддаленому EJB та будуються для з'єднання через мережу.

Військовий проект JEE6 без CDI: може містити EJB Lite, підкріплений несерійними об'єктами JPA.

Військовий проект JEE6 з CDI: Боби, які використовують область сеансу, програми чи розмови, повинні бути серіалізаційними, але боби, які використовують область запиту, не повинні бути серіалізаційними. Таким чином, базові об'єкти JPA, якщо вони є, дотримуватимуться тієї ж семантики.


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інтерфейс.

Зимує

Зимовий режим вимагає лише того, щоб атрибути сутності були Serializable, але не самі сутності.

Однак, застосовуючи специфікацію JPA, всі вимоги JPA, що стосуються Serializableсуб'єктів, застосовуються і до сплячого режиму.

Томат

Відповідно до документації Tomcat , HttpSessionатрибути також повинні бути Serializable:

Щоразу, коли Apache Tomcat нормально вимикається та перезапускається, або коли запускається перезавантаження програми, стандартна реалізація менеджера намагатиметься серіалізувати всі поточно активні сеанси до файлу диска, розташованого через атрибут pathname. Усі такі збережені сеанси будуть деріаріалізовані та активовані (якщо припустити, що вони не закінчилися в середній час) після завершення перезавантаження програми.

Щоб успішно відновити стан атрибутів сеансу, усі такі атрибути ОБОВ'ЯЗКОВО реалізувати інтерфейс java.io.Serializable.

Отже, якщо сутність зберігається в HttpSession, вона повинна реалізувати Serializable.


4

Класи повинні реалізовувати Serializable, якщо ви хочете їх серіалізувати. Це безпосередньо не пов’язано з JPA, і специфікація JPA не вимагає, щоб сутності були серіалізаційними. Якщо Hibernate дійсно скаржиться на це, я вважаю, що це помилка в сплячому режимі, але я припускаю, що ви прямо чи опосередковано займаєтесь чимось іншим із сутностями, що вимагає їх серійності.


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 або angular js тощо ....., може спричинити повторний цикл із виключенням StackOverflow з Jackson quickxml.Так, краще використовувати серіалізатор.


1
  1. У який момент виникає необхідність зробити мою сутність серіалізаційною?

Реалізація ehcache з diskstore як кеш другого рівня (тобто використання @Cacheableанотації на об'єкті чи сховищі / сервісному методі) вимагає Serializable, інакше кеш не зможе ( NotSerializableException) записати сутність в кеш диска.


0

Це також помилка, яка викидається, коли ви передаєте неправильно введений ідентифікатор як другий параметр чимось на зразок em.find () (тобто передача самої сутності, а не її ідентифікатор). Я не вважаю за потрібне фактично оголошувати об'єкти JPA серіалізаційними - це насправді не потрібно, якщо ви не використовуєте referencedColumnName, як описано aman.


0

коли об'єкти JPA використовуються як параметри або значення повернення віддаленими операціями EJB

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.