ChatGPT解决这个技术问题 Extra ChatGPT

When and why JPA entities should implement the Serializable interface?

The question is in the title. Below I just described some of my thoughts and findings.

When I had a very simple domain model (3 tables without any relations), all my entities did NOT implement the Serializable interface.

But when the domain model became more complex, I got a RuntimeException, saying that one of my entities didn't implement Serializable.

I use Hibernate as a JPA implementation, and I wonder:

Is it a vendor-specific requirement/behavior? What happens with my serializable entities? Should they be serializable for storing or for transferring? At which moment it becomes necessary to make my entity serializable?


A
Andrew Tobilko

According to JPA Spec:

If an entity instance is to be passed by value as a detached object (e.g., through a remote interface), the entity class must implement the Serializable interface.

"JSR 220: Enterprise JavaBeansTM,Version 3.0 Java Persistence API Version 3.0, Final Release May 2, 2006"


(+1) looking at the spec is always fruitful
I fail to see why this has so many upvotes. The OP says that it wasn't required when the model was simpler. Sending the objects remotely via Java serialization would ALWAYS require the objects to be Serializable, regardless of its complexity. Obviously this isn't the OP's use case.
I'm not quite sure about hibernate, but with other JPA providers there are operations which require the provider to make a copy of an entity (object). Serializable could be helpful with that, and in the context of persistence more consistent than Cloneable for instance.
This answer is just an info dump and doesn't at all help someone understand why.
B
Bozho

You need your entities to be Serializable if you need to transfer them over-the-wire (serialize them to some other representation), store them in http session (which is in turn serialized to hard disk by the servlet container), etc.

Just for the sake of persistence, Serializable is not needed, at least with Hibernate. But it is a best practice to make them Serializable.


I don't know, maybe my entities are being transferred implicitly somewhere. I use hibernate+spring+jsf and Tomcat. Where in this chain transferring can take place?
@Roman for example the current user (which may be an entity) and all its related entities may end up in the session, which as Bozho says can be serialised to disk by the servlet container.
Best practise in Java is not to make classes serialisable unless you absolutely must for legacy reasons. See Effective Java by Josh Block. What would make it best practice for JPA? OK this is an old answer, these days the need to transfer objects over the wire or store in an http session should be pretty rare.
@dancarter - This is utter nonsense and is also a mischaracterisation of Josh Bloch's advice on the topic. Serialization is an essential part of the language and runtime. It is certainly not reserved for the support of "legacy" code. There are many circumstances in which you SHOULD or MUST implement Serializable. You should however NOT do so without good reason and without understanding the consequences. Josh's point is that the language makes it far too easy to implement Serializable without knowing why or how to do so safely.
Regarding the now very old original post and this equally old answer: JPA providers make extensive use of caching both in memory and on secondary storage. For all but the simplest implementations this will require serialization of entities. Second level caches typically are persistent for recovery and/or overflow to disk. JPA providers must also sometimes make "carbon" copies of entities and requiring implementation of the Serializable interface is the most reliable way to support this.
A
Aaron Digulla

This usually happens if you mix HQL and native SQL queries. In HQL, Hibernate maps the types you pass in to whatever the DB understands. When you run native SQL, then you must do the mapping yourself. If you don't, then the default mapping is to serialize the parameter and send it to the database (in the hope that it does understand it).


This doesn't explain why just "perhaps how" See answer below from Bozho
is that mean entity will be saved in DB with out implementing the serializable interface?
@Hanumantha_3048092 Yes. Entity mapping and Serializable are two different concepts.
@AaronDigulla Can you please explain it by an example or pseudo code.
K
Kevin Peters

JPA specification

According to the JPA specification, an entity should implement Serializable only if it needs to be passed from one JVM to another or if the entity is used by a Stateful Session Bean which needs to be passivated by the EJB container.

If an entity instance is to be passed by value as a detached object (e.g., through a remote interface), the entity class must implement the Serializable interface.

Hibernate

Hibernate only requires that entity attributes are Serializable, but not the entity itself.

However, implementing the JPA specification, all the JPA requirements regarding Serializable entities apply to Hibernate as well.

Tomcat

According to Tomcat documentation, the HttpSession attributes also need to be Serializable:

Whenever Apache Tomcat is shut down normally and restarted, or when an application reload is triggered, the standard Manager implementation will attempt to serialize all currently active sessions to a disk file located via the pathname attribute. All such saved sessions will then be deserialized and activated (assuming they have not expired in the mean time) when the application reload is completed. In order to successfully restore the state of session attributes, all such attributes MUST implement the java.io.Serializable interface.

So, if the entity is stored in the HttpSession, it should implement Serializable.


N
Nathan Tuggy

According to the hibernate docs, while using @JoinColumn annotation:

It has one more parameters named referencedColumnName. This parameter declares the column in the targeted entity that will be used to the join. Note that when using referencedColumnName to a non primary key column, the associated class has to be Serializable.


Thank you for the explanation. I was using @JoinColumn with refenrecedColumnName to a non-primary unique column from another table. This was causing ClassCastException as hibernate could not serialize the entity class.
A
Ankur Singhal

If we just talk about persistence, Serializable is not needed But it is best practice to make the entities Serializable.

If we are exposing domain/entities objects directly exposed to the presentation layer, instead of using DTO , In that case we need to implement Serializable. These domain objects can be stored in HTTPSession for caching/optimization purposes. A http-session can be serialized or clustered. And it is also required for transferring data between JVM-instances.

When we use DTO to decouple persistence layer and service layer, marking the domain objects as Serializable would be counter productive and would violate the “encapsulation”. Then it becomes an anti-pattern.

Composite identifiers

The primary key class must be serializable.

POJO Models

If an entity instance is to be used remotely as a detached object, the entity class must implement the Serializable interface.

Cache
In addition, if you are implementing a clustered second level cache then your entities must be serializable. The identifier has to be Serializable because that’s a JPA requirement since the identifier might be use as the key for a second-level cache entry.

And when we serialize entities make sure to provide explicit serialVersionUID with private access modifier. Because if a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in Java(TM) Object Serialization Specification . Default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization.


for Cache +1. This answer is detailed. It just landed late so the score is not high.
@Ankur " If we are exposing domain/entities objects directly exposed to the presentation layer, instead of using DTO , In that case we need to implement Serializable " this is INCORRECT. According to Joshua Bloch Effective Java "Once an object has been serialized, its encoding can be sent from one VM to another or stored on disk for later deserialization" . In case if presentational layer is Browser(in most cases) , object serialization java inbuilt serialization does not happen, because browser will not understand deserialized stream.
DTO object wo serilization works. Is it because all entity internally are serializaed?
S
Sym-Sym

To complement the nice answer of Conor who referred to the JSR-317 specifications. Typically, EAR projects consist of an EJB module with the EJBs exposed via a remote interface. In this one case you need to make your entity beans serializable as they are aggregated in the remote EJB and are built to be wired through the network.

A JEE6 war project without CDI: can contain EJB lite backed by non-serializable JPA entities.

A JEE6 war project with CDI: Beans that use session, application, or conversation scope must be serializable, but beans that use request scope do not have to be serializable. Thus the underlying JPA entity beans -if any- would follow the same semantics.


N
Nathan Hughes

I believe your problem is related to having a field of a complex type (class) which isn't annotated. In such cases the default handling will be storing the object in its serialized form in the database (which probably isn't what you meant to do) Example:

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

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

In the above case the CustomerData will be saved in a byte array field in the database in its serialized form.


This is an interesting one, so as long as CustomerData implements Serializable, when loading a Customer it will be able to deserialize the customerData?
j
jarnbjo

Classes must implement Serializable if you want to serialize them. This is not directly related to JPA and the JPA specification does not require that entities are serializable. If Hibernate really complains about this, I suppose it is a Hibernate bug, but I suppose that you directly or indirectly are doing something else with the entities, which require them to be serializable.


A
Arun K

Please refer http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_to it says, The implementation of java.io.Serializable is simply required for transfering data via IIOP or JRMP (RMI) between JVM-instances. In case of a pure web application the domain objects are sometimes stored in HTTPSession for caching / optimization purposes. A http-session can be serialized (passivation) or clustered. In both cases all the content have to be Serializable.


M
Michal

At which moment it becomes necessary to make my entity serializable?

Implementing ehcache with diskstore as second level cache (i.e. using @Cacheable annotation on entity or repository/service method) requires Serializable, otherwise the cache will fail (NotSerializableException) to write the entity to the disk cache.


t
tamil

remote hit using postman or ajax or angular js etc....., may cause the repeat cycle with StackOverflow exception with Jackson fasterxml.So, it is better to use serializer.


S
SAR

when JPA entities are used as parameters or return values by the remote EJB operations


A
Amalgovinus

This is also the error that's thrown when you pass an incorrectly-typed ID as the second param to something like em.find() (i.e. passing the entity itself rather than its ID). I haven't found it yet necessary to actually declare JPA entities serializable--it's not really necessary unless you're using referencedColumnName as described by aman.