Wann und warum sollten JPA-Entitäten eine serialisierbare Schnittstelle implementieren?

151

Die Frage steht im Titel. Im Folgenden habe ich nur einige meiner Gedanken und Erkenntnisse beschrieben.

Als ich ein sehr einfaches Domänenmodell hatte (3 Tabellen ohne Beziehungen), implementierten alle meine Entitäten NICHT Serializable.

Aber als das Domänenmodell komplexer wurde, bekam ich RuntimeException, die besagte, dass eine meiner Entitäten Serializable nicht implementiert hat.

Ich verwende Hibernate als JPA-Implementierung.

Ich wundere mich:

  1. Ist es herstellerspezifische Anforderung / Verhalten?
  2. Was passiert mit meinen serialisierbaren Entitäten? Sollten sie zum Speichern oder Übertragen serialisierbar sein?
  3. In welchem ​​Moment wird es notwendig, meine Entität serialisierbar zu machen?
römisch
quelle

Antworten:

59

Dies geschieht normalerweise, wenn Sie HQL- und native SQL-Abfragen mischen. In HQL ordnet Hibernate die Typen, die Sie übergeben, dem zu, was die Datenbank versteht. Wenn Sie natives SQL ausführen, müssen Sie die Zuordnung selbst vornehmen. Wenn Sie dies nicht tun, besteht die Standardzuordnung darin, den Parameter zu serialisieren und an die Datenbank zu senden (in der Hoffnung, dass er ihn versteht).

Aaron Digulla
quelle
Dies erklärt nicht, warum nur "vielleicht wie" Siehe Antwort unten von Bozho
Chrips
Wird diese mittlere Entität in der Datenbank gespeichert, ohne dass die serialisierbare Schnittstelle implementiert wird?
Hanumantha_3048092
@ Hanumantha_3048092 Ja. Entity Mapping und Serializablesind zwei verschiedene Konzepte.
Aaron Digulla
@AaronDigulla Kannst du es bitte anhand eines Beispiels oder Pseudocodes erklären?
sdindiver
110

Laut JPA-Spezifikation:

Wenn eine Entitätsinstanz als getrenntes Objekt (z. B. über eine Remote-Schnittstelle) als Wert übergeben werden soll, muss die Entitätsklasse die serialisierbare Schnittstelle implementieren.

"JSR 220: Enterprise JavaBeansTM, Version 3.0 Java Persistence API Version 3.0, endgültige Version 2. Mai 2006"

Conor
quelle
14
(+1) Blick auf die Spezifikation ist immer fruchtbar
Bozho
20
Ich verstehe nicht, warum dies so viele positive Stimmen hat. Das OP sagt, dass es nicht erforderlich war, als das Modell einfacher war. Das Remote-Senden der Objekte über die Java-Serialisierung würde IMMER erfordern, dass die Objekte unabhängig von ihrer Komplexität serialisierbar sind. Offensichtlich ist dies nicht der Anwendungsfall des OP.
Robin
Ich bin mir über den Ruhezustand nicht ganz sicher, aber bei anderen JPA-Anbietern gibt es Vorgänge, bei denen der Anbieter eine Kopie einer Entität (eines Objekts) erstellen muss. Serializablekönnte dabei hilfreich sein und im Kontext der Persistenz konsistenter als Cloneablezum Beispiel.
JimmyB
Diese Antwort ist nur ein Info-Dump und hilft niemandem zu verstehen, warum.
Chrips
59

Sie müssen Ihre Entitäten sein, Serializablewenn Sie sie drahtlos übertragen (in eine andere Darstellung serialisieren), in einer http-Sitzung speichern müssen (die wiederum vom Servlet-Container auf die Festplatte serialisiert wird) usw.

Nur aus Gründen der Beharrlichkeit wird Serializablees zumindest im Ruhezustand nicht benötigt. Aber es ist eine bewährte Methode, sie zu erstellen Serializable.

Bozho
quelle
2
Ich weiß nicht, vielleicht werden meine Entitäten implizit irgendwohin übertragen. Ich benutze Hibernate + Spring + JSF und Tomcat. Wo in dieser Kette kann eine Übertragung stattfinden?
Roman
@Roman zum Beispiel können der aktuelle Benutzer (der eine Entität sein kann) und alle zugehörigen Entitäten in der Sitzung enden, die, wie Bozho sagt, vom Servlet-Container auf die Festplatte serialisiert werden kann.
OrangeDog
Dies ist die beste Antwort "warum und wann"! Klar! Vielen Dank
chrips
13

Laut den Dokumenten für den Ruhezustand können Sie bei Verwendung der Annotation @JoinColumn:

Es hat einen weiteren Parameter benannt referencedColumnName. Dieser Parameter deklariert die Spalte in der Zielentität, die für den Join verwendet wird. Beachten Sie, dass bei Verwendung referencedColumnNameeiner Nicht-Primärschlüsselspalte die zugehörige Klasse sein muss Serializable.

Aman Maharjan
quelle
8

Als Ergänzung zu der netten Antwort von Conor, der sich auf die JSR-317-Spezifikationen bezog. In der Regel bestehen EAR-Projekte aus einem EJB-Modul, wobei die EJBs über eine Remote-Schnittstelle verfügbar gemacht werden. In diesem Fall müssen Sie Ihre Entity-Beans serialisierbar machen, da sie in der Remote-EJB aggregiert und für die Verkabelung über das Netzwerk erstellt wurden.

Ein JEE6-Kriegsprojekt ohne CDI: Kann EJB Lite enthalten, das von nicht serialisierbaren JPA-Entitäten unterstützt wird.

Ein JEE6-Kriegsprojekt mit CDI: Beans, die den Sitzungs-, Anwendungs- oder Konversationsbereich verwenden, müssen serialisierbar sein, Beans, die den Anforderungsbereich verwenden, müssen jedoch nicht serialisierbar sein. Somit würden die zugrunde liegenden JPA-Entity-Beans - falls vorhanden - der gleichen Semantik folgen.

Sym-Sym
quelle
7

Wenn wir nur über Persistenz sprechen, Serializablewird dies nicht benötigt. Es ist jedoch eine bewährte Methode, die Entitäten zu erstellen Serializable.

Wenn wir aussetzen domain/ entitiesObjekte direkt an die Präsentationsschicht ausgesetzt ist , anstelle der Verwendung von DTO, in diesem Fall müssen wir implementieren Serializable. Diese Domänenobjekte können zu HTTPSessionCaching- / Optimierungszwecken gespeichert werden. Eine http-Sitzung kann serialisiert oder geclustert werden. Und es ist auch für die Übertragung von Daten zwischen JVM-Instanzen erforderlich.

Wenn wir die DTOPersistenzschicht und die Serviceschicht entkoppeln, markiert das Markieren der Domänenobjekte als Serializablekontraproduktiv und würde das " encapsulation" verletzen . Dann wird es ein Anti-Muster.

Zusammengesetzte Bezeichner

Die Primärschlüsselklasse muss serialisierbar sein.

POJO-Modelle

Wenn eine Entitätsinstanz remote als getrenntes Objekt verwendet werden soll, muss die Entitätsklasse die SerializableSchnittstelle implementieren .

Cache
Wenn Sie eine clusteredzweite Ebene implementieren cache, müssen dies auch Ihre Entitäten sein serializable. Der Bezeichner muss sein, Serializableda dies eine JPA-Anforderung ist, da er identifiermöglicherweise als Schlüssel für einen Cache-Eintrag der zweiten Ebene verwendet wird.

Und wenn wir Entitäten serialisieren, stellen Sie sicher, dass Sie explizit den serialVersionUIDModifikator für den privaten Zugriff angeben. Wenn eine serializableKlasse a nicht explizit deklariert serialVersionUID, berechnet die Serialisierungslaufzeit einen Standardwert serialVersionUIDfür diese Klasse basierend auf verschiedenen Aspekten der Klasse, wie in Java (TM) Object Serialization Specification beschrieben. Die Standardberechnung serialVersionUIDreagiert sehr empfindlich auf Klassendetails, die je nach Compiler-Implementierung variieren können, und kann daher InvalidClassExceptionswährend der Deserialisierung zu unerwarteten Ergebnissen führen .

Ankur Singhal
quelle
6

Ich glaube, Ihr Problem hängt damit zusammen, dass ein Feld eines komplexen Typs (einer Klasse) nicht mit Anmerkungen versehen ist. In solchen Fällen wird das Objekt standardmäßig in seiner serialisierten Form in der Datenbank gespeichert (was wahrscheinlich nicht das ist, was Sie beabsichtigt haben). Beispiel:

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

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

In dem obigen Fall werden die Kundendaten in ihrer serialisierten Form in einem Byte-Array-Feld in der Datenbank gespeichert.

Avner Levy
quelle
5

JPA-Spezifikation

Gemäß der JPA-Spezifikation sollte eine Entität Serializablenur implementiert werden , wenn sie von einer JVM an eine andere übergeben werden muss oder wenn die Entität von einer Stateful Session Bean verwendet wird, die vom EJB-Container passiviert werden muss.

Wenn eine Entitätsinstanz als getrenntes Objekt als Wert übergeben werden soll (z. B. über eine Remote-Schnittstelle), muss die Entitätsklasse die SerializableSchnittstelle implementieren .

Überwintern

Für den Ruhezustand sind nur Entitätsattribute erforderlich, Serializablenicht jedoch die Entität selbst.

Bei der Implementierung der JPA-Spezifikation gelten jedoch alle JPA-Anforderungen in Bezug auf SerializableEntitäten auch für den Ruhezustand.

Kater

Laut Tomcat-Dokumentation müssen die HttpSessionAttribute auch sein Serializable:

Immer wenn Apache Tomcat normal heruntergefahren und neu gestartet wird oder wenn ein erneutes Laden der Anwendung ausgelöst wird, versucht die Standard-Manager-Implementierung, alle derzeit aktiven Sitzungen in eine Festplattendatei zu serialisieren, die sich über das Attribut pathname befindet. Alle diese gespeicherten Sitzungen werden dann deserialisiert und aktiviert (vorausgesetzt, sie sind in der Zwischenzeit nicht abgelaufen), wenn das erneute Laden der Anwendung abgeschlossen ist.

Um den Status der Sitzungsattribute erfolgreich wiederherzustellen, MÜSSEN alle diese Attribute die Schnittstelle java.io.Serializable implementieren.

Wenn die Entität in der gespeichert ist HttpSession, sollte sie implementiert werden Serializable.

Vlad Mihalcea
quelle
4

Klassen müssen Serializable implementieren, wenn Sie sie serialisieren möchten. Dies steht nicht in direktem Zusammenhang mit JPA und die JPA-Spezifikation erfordert nicht, dass Entitäten serialisierbar sind. Wenn sich Hibernate wirklich darüber beschwert, ist es vermutlich ein Hibernate-Fehler, aber ich nehme an, dass Sie direkt oder indirekt etwas anderes mit den Entitäten tun, für die sie serialisierbar sein müssen.

jarnbjo
quelle
3

Weitere Informationen finden Sie unter http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_to . Die Implementierung von java.io.Serializable ist lediglich für die Übertragung von Daten über IIOP oder JRMP (RMI) zwischen JVM-Instanzen erforderlich. Bei einer reinen Webanwendung werden die Domänenobjekte manchmal zu Zwischenspeicherungs- / Optimierungszwecken in HTTPSession gespeichert. Eine http-Sitzung kann serialisiert (Passivierung) oder geclustert werden. In beiden Fällen muss der gesamte Inhalt serialisierbar sein.

Arun K.
quelle
1

Remote-Treffer mit Postman oder Ajax oder eckigen Js usw. können den Wiederholungszyklus mit StackOverflow-Ausnahme mit Jackson schnellerxml verursachen. Daher ist es besser, den Serializer zu verwenden.

Tamil
quelle
1
  1. In welchem ​​Moment wird es notwendig, meine Entität serialisierbar zu machen?

Das Implementieren von ehcache mit Diskstore als Cache der zweiten Ebene (dh Verwenden von @CacheableAnmerkungen zur Entität oder zur Repository- / Servicemethode) erfordert Serializable, andernfalls kann der Cache NotSerializableExceptiondie Entität nicht in den Disk-Cache schreiben ( ).

Michal
quelle
0

Dies ist auch der Fehler, der ausgelöst wird, wenn Sie eine falsch eingegebene ID als zweiten Parameter an etwas wie em.find () übergeben (dh die Entität selbst anstelle ihrer ID übergeben). Ich habe es noch nicht für notwendig befunden, JPA-Entitäten tatsächlich als serialisierbar zu deklarieren - es ist nicht wirklich notwendig, es sei denn, Sie verwenden referencedColumnName, wie von aman beschrieben.

Amalgovinus
quelle
0

wenn JPA-Entitäten von den Remote-EJB-Operationen als Parameter oder Rückgabewerte verwendet werden

SAR
quelle