Quand et pourquoi les entités JPA devraient-elles implémenter une interface sérialisable?

151

La question est dans le titre. Ci-dessous, je viens de décrire certaines de mes pensées et conclusions.

Quand j'avais un modèle de domaine très simple (3 tables sans aucune relation), toutes mes entités n'ont PAS implémenté Serializable.

Mais quand le modèle de domaine est devenu plus complexe, j'ai eu RuntimeException qui a dit qu'une de mes entités n'a pas implémenté Serializable.

J'utilise Hibernate comme implémentation JPA.

Je me demande:

  1. Est-ce une exigence / un comportement spécifique au fournisseur?
  2. Que se passe-t-il avec mes entités sérialisables? Devraient-ils être sérialisables pour le stockage ou pour le transfert?
  3. A quel moment il devient nécessaire de rendre mon entité sérialisable?
romain
la source

Réponses:

59

Cela se produit généralement si vous mélangez des requêtes HQL et SQL natives. Dans HQL, Hibernate mappe les types que vous transmettez à ce que la base de données comprend. Lorsque vous exécutez SQL natif, vous devez effectuer vous-même le mappage. Si vous ne le faites pas, le mappage par défaut consiste à sérialiser le paramètre et à l'envoyer à la base de données (dans l'espoir qu'il le comprenne).

Aaron Digulla
la source
Cela n'explique pas pourquoi juste "peut-être comment" Voir la réponse ci-dessous de Bozho
chrips
est-ce que l'entité moyenne sera enregistrée dans la base de données sans implémenter l'interface sérialisable?
Hanumantha_3048092
@ Hanumantha_3048092 Oui. Mappage d'entité et Serializablesont deux concepts différents.
Aaron Digulla le
@AaronDigulla Pouvez-vous l'expliquer par un exemple ou un pseudo code.
sdindiver
110

Selon les spécifications JPA:

Si une instance d'entité doit être transmise par valeur en tant qu'objet détaché (par exemple, via une interface distante), la classe d'entité doit implémenter l'interface Serializable.

«JSR 220: Enterprise JavaBeansTM, version 3.0 API de persistance Java version 3.0, version finale le 2 mai 2006»

Conor
la source
14
(+1) regarder les spécifications est toujours fructueux
Bozho
20
Je ne vois pas pourquoi cela a tant de votes positifs. Le PO dit que ce n'était pas nécessaire lorsque le modèle était plus simple. L'envoi des objets à distance via la sérialisation Java nécessiterait TOUJOURS que les objets soient sérialisables, quelle que soit leur complexité. Ce n'est évidemment pas le cas d'utilisation de l'OP.
Robin
Je ne suis pas tout à fait sûr de la mise en veille prolongée, mais avec d'autres fournisseurs JPA, il existe des opérations qui obligent le fournisseur à faire une copie d'une entité (objet). Serializablepourrait être utile avec cela, et dans le contexte de la persistance plus cohérente que Cloneablepar exemple.
JimmyB
Cette réponse n'est qu'un vidage d'informations et n'aide pas du tout quelqu'un à comprendre pourquoi.
chrips
59

Vous avez besoin que vos entités soient Serializable si vous devez les transférer via le fil (les sérialiser vers une autre représentation), les stocker dans une session http (qui est à son tour sérialisée sur le disque dur par le conteneur de servlet), etc.

Juste pour des raisons de persistance, Serializablen'est pas nécessaire, du moins avec Hibernate. Mais c'est une bonne pratique de les faire Serializable.

Bozho
la source
2
Je ne sais pas, peut-être que mes entités sont transférées implicitement quelque part. J'utilise hibernate + spring + jsf et Tomcat. Où dans cette chaîne le transfert peut-il avoir lieu?
Roman
@Roman, par exemple, l'utilisateur actuel (qui peut être une entité) et toutes ses entités associées peuvent se retrouver dans la session, qui, comme Bozho le dit, peut être sérialisée sur disque par le conteneur de servlet.
OrangeDog
CECI est la meilleure réponse "pourquoi et quand"! Clair! Merci
chrips
13

Selon la documentation Hibernate, lors de l'utilisation de l'annotation @JoinColumn:

Il a un autre paramètre nommé referencedColumnName. Ce paramètre déclare la colonne de l'entité ciblée qui sera utilisée pour la jointure. Notez que lorsque vous utilisez referencedColumnNameune colonne de clé non primaire, la classe associée doit être Serializable.

aman maharjan
la source
8

Pour compléter la belle réponse de Conor qui a fait référence aux spécifications du JSR-317. En règle générale, les projets EAR consistent en un module EJB avec les EJB exposés via une interface distante. Dans ce cas précis, vous devez rendre vos beans entité sérialisables car ils sont agrégés dans l'EJB distant et sont construits pour être câblés via le réseau.

Un projet de guerre JEE6 sans CDI: peut contenir EJB lite soutenu par des entités JPA non sérialisables.

Un projet de guerre JEE6 avec CDI: les beans qui utilisent l'étendue de session, d'application ou de conversation doivent être sérialisables, mais les beans qui utilisent l'étendue de requête ne doivent pas nécessairement être sérialisables. Ainsi, les beans entité JPA sous-jacents - le cas échéant - suivraient la même sémantique.

Sym-Sym
la source
7

Si nous parlons simplement de persistance, ce Serializablen'est pas nécessaire, mais il est préférable de créer les entités Serializable.

Si nous exposons domain/ entitiesobjets directement exposés à la couche de présentation, au lieu d'utiliser DTO, Dans ce cas, nous devons implémenter Serializable. Ces objets de domaine peuvent être stockés à des HTTPSessionfins de mise en cache / d'optimisation. Une session http peut être sérialisée ou mise en cluster. Et il est également nécessaire pour le transfert de données entre JVM-instances.

Lorsque nous utilisons DTOpour découpler la couche de persistance et la couche de service, marquer les objets de domaine comme Serializableétant contre-productif et violerait le « encapsulation». Ensuite, cela devient un anti-modèle.

Identifiants composites

La classe de clé primaire doit être sérialisable.

Modèles POJO

Si une instance d'entité doit être utilisée à distance en tant qu'objet détaché, la classe d'entité doit implémenter l' Serializableinterface.

Cache
De plus, si vous implémentez un clustereddeuxième niveau, cachevos entités doivent l'être serializable. L'identifiant doit être Serializableparce que c'est une exigence JPA car il identifierpeut être utilisé comme clé pour une entrée de cache de deuxième niveau.

Et lorsque nous sérialisons des entités, assurez-vous de fournir explicitement serialVersionUIDun modificateur d'accès privé. Parce que si une serializableclasse ne déclare pas explicitement a serialVersionUID, alors le runtime de sérialisation calculera une serialVersionUIDvaleur par défaut pour cette classe en fonction de divers aspects de la classe, comme décrit dans Spécification de sérialisation d'objets Java (TM). Le serialVersionUIDcalcul par défaut est très sensible aux détails de classe qui peuvent varier en fonction des implémentations du compilateur et peuvent donc entraîner des résultats inattendus InvalidClassExceptionslors de la désérialisation.

Ankur Singhal
la source
6

Je crois que votre problème est lié au fait d'avoir un champ de type complexe (classe) qui n'est pas annoté. Dans de tels cas, la gestion par défaut stockera l'objet sous sa forme sérialisée dans la base de données (ce qui n'est probablement pas ce que vous vouliez faire) Exemple:

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

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

Dans le cas ci-dessus, CustomerData sera enregistré dans un champ de tableau d'octets de la base de données sous sa forme sérialisée.

Avner Levy
la source
5

Spécification JPA

Selon la spécification JPA, une entité ne doit implémenter Serializableque si elle doit être transmise d'une JVM à une autre ou si l'entité est utilisée par un Stateful Session Bean qui doit être passivé par le conteneur EJB.

Si une instance d'entité doit être transmise par valeur en tant qu'objet détaché (par exemple, via une interface distante), la classe d'entité doit implémenter l' Serializableinterface.

Hiberner

Hibernate exige uniquement que les attributs d'entité soient Serializable , mais pas l'entité elle-même.

Cependant, en implémentant la spécification JPA, toutes les exigences JPA concernant Serializable entités s'appliquent également à Hibernate.

Matou

Selon la documentation Tomcat , les HttpSessionattributs doivent également être Serializable:

À chaque fois qu'Apache Tomcat est arrêté et redémarré normalement, ou lorsqu'un rechargement d'application est déclenché, l'implémentation standard de Manager tentera de sérialiser toutes les sessions actuellement actives dans un fichier disque localisé via l'attribut chemin. Toutes ces sessions enregistrées seront ensuite désérialisées et activées (en supposant qu'elles n'ont pas expiré dans l'intervalle) lorsque le rechargement de l'application est terminé.

Afin de restaurer avec succès l'état des attributs de session, tous ces attributs DOIVENT implémenter l'interface java.io.Serializable.

Ainsi, si l'entité est stockée dans le HttpSession, elle doit implémenter Serializable.

Vlad Mihalcea
la source
4

Les classes doivent implémenter Serializable si vous souhaitez les sérialiser. Ceci n'est pas directement lié à JPA et la spécification JPA n'exige pas que les entités soient sérialisables. Si Hibernate se plaint vraiment de cela, je suppose que c'est un bogue d'Hibernate, mais je suppose que vous faites directement ou indirectement autre chose avec les entités, ce qui nécessite qu'elles soient sérialisables.

Jarnbjo
la source
3

Veuillez vous référer à http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_to il est dit, l'implémentation de java.io.Serializable est simplement nécessaire pour le transfert de données via IIOP ou JRMP (RMI) entre les instances JVM. Dans le cas d'une application Web pure, les objets de domaine sont parfois stockés dans HTTPSession à des fins de mise en cache / d'optimisation. Une session http peut être sérialisée (passivation) ou mise en cluster. Dans les deux cas, tout le contenu doit être sérialisable.

Arun K
la source
1

hit à distance en utilisant postman ou ajax ou angular js etc.

Tamil
la source
1
  1. A quel moment il devient nécessaire de rendre mon entité sérialisable?

L'implémentation d'ehcache avec diskstore comme cache de second niveau (c'est-à-dire en utilisant l' @Cacheableannotation sur l'entité ou la méthode référentiel / service) nécessite Serializable, sinon le cache échouera ( NotSerializableException) pour écrire l'entité dans le cache disque.

Michal
la source
0

C'est aussi l'erreur qui est lancée lorsque vous passez un ID mal tapé comme deuxième paramètre à quelque chose comme em.find () (c'est-à-dire en passant l'entité elle-même plutôt que son ID). Je n'ai pas encore trouvé nécessaire de déclarer réellement les entités JPA sérialisables - ce n'est pas vraiment nécessaire, sauf si vous utilisez referencedColumnName comme décrit par aman.

Amalgovinus
la source
0

lorsque des entités JPA sont utilisées comme paramètres ou retournent des valeurs par les opérations EJB distantes

SAR
la source