Quando e perché le entità JPA dovrebbero implementare l'interfaccia serializzabile?


151

La domanda è nel titolo. Di seguito ho appena descritto alcuni dei miei pensieri e scoperte.

Quando avevo un modello di dominio molto semplice (3 tabelle senza relazioni) tutte le mie entità NON implementavano Serializable.

Ma quando il modello di dominio è diventato più complesso, ho ottenuto RuntimeException che diceva che una delle mie entità non implementava Serializable.

Uso Hibernate come implementazione di JPA.

Mi chiedo:

  1. È un requisito / comportamento specifico del fornitore?
  2. Cosa succede con le mie entità serializzabili? Dovrebbero essere serializzabili per la memorizzazione o per il trasferimento?
  3. In quale momento diventa necessario rendere la mia entità serializzabile?

Risposte:


59

Questo di solito accade se si mescolano query HQL e SQL native. In HQL, Hibernate mappa i tipi che passi a qualunque cosa il DB capisca. Quando esegui SQL nativo, devi eseguire tu stesso il mapping. In caso contrario, la mappatura predefinita è serializzare il parametro e inviarlo al database (nella speranza che lo capisca).


Questo non spiega perché semplicemente "forse come" Vedi la risposta di seguito da Bozho
chrips

è che l'entità media verrà salvata nel DB senza implementare l'interfaccia serializzabile?
Hanumantha_3048092

@ Hanumantha_3048092 Sì. Mappatura delle entità e Serializablesono due concetti diversi.
Aaron Digulla

@AaronDigulla Puoi per favore spiegarlo con un esempio o un pseudo codice.
sdindiver,

110

Secondo le specifiche JPA:

Se un'istanza di entità deve essere passata per valore come oggetto separato (ad es. Attraverso un'interfaccia remota), la classe di entità deve implementare l'interfaccia serializzabile.

"JSR 220: Enterprise JavaBeansTM, Versione 3.0 Java Persistence API Versione 3.0, versione finale 2 maggio 2006"


14
(+1) guardare le specifiche è sempre fruttuoso
Bozho

20
Non riesco a capire perché questo abbia tanti voti positivi. L'OP afferma che non era necessario quando il modello era più semplice. L'invio remoto degli oggetti tramite serializzazione Java richiederebbe SEMPRE che gli oggetti siano serializzabili, indipendentemente dalla sua complessità. Ovviamente questo non è il caso d'uso dell'OP.
Robin,

Non sono del tutto sicuro dell'ibernazione, ma con altri provider JPA ci sono operazioni che richiedono al provider di fare una copia di un'entità (oggetto). Serializablepotrebbe essere d'aiuto in questo, e nel contesto della persistenza più coerente rispetto Cloneablead esempio.
JimmyB,

Questa risposta è solo una discarica di informazioni e non aiuta affatto qualcuno a capire il perché.
Chrips

59

È necessario che le entità lo siano Serializablese è necessario trasferirle via cavo (serializzarle in un'altra rappresentazione), memorizzarle nella sessione http (che a sua volta è serializzata su disco rigido dal contenitore servlet), ecc.

Solo per motivi di persistenza, Serializablenon è necessario, almeno con Hibernate. Ma è una buona pratica farli Serializable.


2
Non lo so, forse le mie entità vengono trasferite implicitamente da qualche parte. Uso hibernate + spring + jsf e Tomcat. Dove può avvenire il trasferimento in questa catena?
Roman

@Roman, ad esempio, l'utente corrente (che potrebbe essere un'entità) e tutte le sue entità correlate potrebbero finire nella sessione, che come dice Bozho può essere serializzata su disco dal contenitore servlet.
OrangeDog

QUESTA è la migliore risposta "perché e quando"! Chiaro! Grazie
chrips

13

Secondo i documenti di ibernazione , durante l'utilizzo dell'annotazione @JoinColumn:

Ha un altro parametro denominato referencedColumnName. Questo parametro dichiara la colonna nell'entità target che verrà utilizzata per il join. Si noti che quando si utilizza referencedColumnNameuna colonna chiave non primaria, la classe associata deve essere Serializable.


8

Per completare la bella risposta di Conor che ha fatto riferimento alle specifiche JSR-317. In genere, i progetti EAR consistono in un modulo EJB con gli EJB esposti attraverso un'interfaccia remota. In questo caso è necessario rendere serializzabili i bean di entità poiché sono aggregati nel bean remoto e sono progettati per essere cablati attraverso la rete.

Un progetto di guerra JEE6 senza CDI: può contenere EJB lite supportato da entità JPA non serializzabili.

Un progetto di guerra JEE6 con CDI: i bean che utilizzano l'ambito della sessione, dell'applicazione o della conversazione devono essere serializzabili, ma i bean che utilizzano l'ambito della richiesta non devono essere serializzabili. Pertanto, i bean di entità JPA sottostanti, se presenti, seguiranno la stessa semantica.


7

Se parliamo solo di persistenza, Serializablenon è necessario, ma è buona prassi creare entità Serializable.

Se stiamo esponendo domain/ entitiesoggetti direttamente esposti al livello di presentazione, anziché utilizzare DTO, In tal caso dobbiamo implementare Serializable. Questi oggetti di dominio possono essere archiviati HTTPSessionper scopi di memorizzazione nella cache / ottimizzazione. Una sessione http può essere serializzata o raggruppata. Ed è anche richiesto per il trasferimento di dati tra JVMistanze.

Quando usiamo DTOper disaccoppiare il livello di persistenza e il livello di servizio, contrassegnando gli oggetti del dominio come Serializablecontroproducenti e violerebbero il " encapsulation". Quindi diventa un anti-pattern.

Identificatori compositi

La classe di chiave primaria deve essere serializzabile.

Modelli POJO

Se un'istanza di entità deve essere utilizzata in remoto come oggetto separato, la classe di entità deve implementare l' Serializableinterfaccia.

Cache
Inoltre, se stai implementando un clusteredsecondo livello, le cachetue entità devono esserlo serializable. L'identificatore deve essere Serializabledovuto al fatto che si tratta di un requisito JPA poiché identifierpotrebbe essere utilizzato come chiave per una voce della cache di secondo livello.

E quando serializziamo le entità assicurati di fornire esplicitamente serialVersionUIDun modificatore di accesso privato. Perché se una serializableclasse non dichiara esplicitamente a serialVersionUID, il runtime di serializzazione calcolerà un serialVersionUIDvalore predefinito per quella classe in base a vari aspetti della classe, come descritto nelle Specifiche di serializzazione degli oggetti Java (TM). Il serialVersionUIDcalcolo predefinito è altamente sensibile ai dettagli della classe che possono variare a seconda delle implementazioni del compilatore e può quindi comportare imprevisti InvalidClassExceptionsdurante la deserializzazione.


6

Credo che il tuo problema sia correlato alla presenza di un campo di tipo complesso (classe) che non è annotato. In questi casi la gestione predefinita memorizzerà l'oggetto nella sua forma serializzata nel database (che probabilmente non è quello che intendevi fare) Esempio:

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

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

Nel caso sopra, CustomerData verrà salvato in un campo array di byte nel database nella sua forma serializzata.


5

Specifica JPA

Secondo la specifica JPA, un'entità dovrebbe implementare Serializablesolo se deve essere passata da una JVM a un'altra o se l'entità è utilizzata da un bean di sessione stateful che deve essere passivato dal contenitore EJB.

Se un'istanza di entità deve essere passata per valore come oggetto separato (ad es. Attraverso un'interfaccia remota), la classe di entità deve implementare l' Serializableinterfaccia.

Hibernate

L'ibernazione richiede solo che gli attributi dell'entità lo siano Serializable, ma non l'entità stessa.

Tuttavia, implementando la specifica JPA, tutti i requisiti JPA relativi alle Serializableentità si applicano anche a Hibernate.

micio

Secondo la documentazione di Tomcat , gli HttpSessionattributi devono anche essere Serializable:

Ogni volta che Apache Tomcat viene spento e riavviato normalmente o quando viene avviata una ricarica dell'applicazione, l'implementazione standard di Manager tenterà di serializzare tutte le sessioni attualmente attive su un file su disco che si trova tramite l'attributo pathname. Tutte le sessioni salvate verranno quindi deserializzate e attivate (supponendo che non siano scadute nel frattempo) al completamento del ricaricamento dell'applicazione.

Per ripristinare correttamente lo stato degli attributi della sessione, tutti questi attributi DEVONO implementare l'interfaccia java.io.Serializable.

Quindi, se l'entità è archiviata in HttpSession, dovrebbe implementarsi Serializable.


4

Le classi devono implementare Serializable se si desidera serializzarle. Questo non è direttamente correlato a JPA e la specifica JPA non richiede che le entità siano serializzabili. Se Hibernate si lamenta davvero di questo, suppongo che sia un bug di Hibernate, ma suppongo che tu stia facendo qualcos'altro direttamente o indirettamente con le entità, che richiedono che siano serializzabili.


3

Si prega di fare riferimento a http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_ per dirlo, L'implementazione di java.io.Serializable è semplicemente necessaria per il trasferimento di dati tramite IIOP o JRMP (RMI) tra istanze JVM. Nel caso di un'applicazione Web pura, gli oggetti di dominio vengono talvolta archiviati in HTTPSession per scopi di memorizzazione nella cache / ottimizzazione. Una sessione http può essere serializzata (passivazione) o raggruppata. In entrambi i casi tutto il contenuto deve essere serializzabile.


1

il colpo remoto che utilizza postino o ajax o angolare js ecc ....., può causare il ciclo di ripetizione con l'eccezione StackOverflow con Jackson fastxml. Quindi, è meglio usare il serializzatore.


1
  1. In quale momento diventa necessario rendere la mia entità serializzabile?

L'implementazione di ehcache con diskstore come cache di secondo livello (ovvero utilizzando l' @Cacheableannotazione sull'entità o il metodo repository / servizio) richiede Serializable, altrimenti la cache non riuscirà ( NotSerializableException) a scrivere l'entità nella cache del disco.


0

Questo è anche l'errore generato quando si passa un ID digitato in modo errato come secondo parametro a qualcosa come em.find () (ovvero passando l'entità stessa anziché il suo ID). Non ho ancora trovato la necessità di dichiarare effettivamente le entità JPA serializzabili - non è davvero necessario a meno che non si stia usando referencedColumnName come descritto da Aman.


0

quando le entità JPA vengono utilizzate come parametri o valori di ritorno dalle operazioni EJB remote

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.