问题
I am developing an application in javafx that connects via RMI with an EAR. This EAR connects to a SQLServer DB and maps POJOS using hibernate.
These POJOS contain bidirectional OneToMany and ManyToOne relationships. As a consequence these relationships are mapped as List .
Company.java
@Entity
@Table(name = "Company")
public class Company implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name="id_company",nullable = false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@OneToMany(mappedBy = "company",cascade = CascadeType.ALL )
@ElementCollection
private List<Client> Clients;
//GETTERS&SETTERS
}
Client.java
@Entity
@Table(name = "Client")
public class Client implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name="id_client",nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne
private Company company;
//GETTERS&SETTERS
}
When I execute this, T being Company:
public default T selectById(Serializable id, Class<T> entityClass,Session session)throws HibernateException {
T obj = null;
obj = session.get(entityClass, id);
return obj;
}
The result is the POJO with all the corresponding information, but in debug view see this:

The object is successfully instantiated and my desktop application receives the object perfectly, but if the object sent it to the server again using a method that receives as a parameter the object Company then I have this Error.
javax.ejb.EJBException: java.io.StreamCorruptedException: serialVersionUID does not match!
at org.jboss.as.ejb3.remote.AssociationImpl.receiveInvocationRequest(AssociationImpl.java:128)
at org.jboss.ejb.protocol.remote.EJBServerChannel$ReceiverImpl.handleInvocationRequest(EJBServerChannel.java:450)
at org.jboss.ejb.protocol.remote.EJBServerChannel$ReceiverImpl.handleMessage(EJBServerChannel.java:188)
at org.jboss.remoting3.remote.RemoteConnectionChannel.lambda$handleMessageData$3(RemoteConnectionChannel.java:430)
at org.jboss.remoting3.EndpointImpl$TrackingExecutor.lambda$execute$0(EndpointImpl.java:926)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.io.StreamCorruptedException: serialVersionUID does not match!
at org.jboss.marshalling.AbstractClassResolver.resolveClass(AbstractClassResolver.java:108)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadClassDescriptor(RiverUnmarshaller.java:1025)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadNewObject(RiverUnmarshaller.java:1354)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:275)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:223)
at org.jboss.marshalling.river.RiverUnmarshaller.readFields(RiverUnmarshaller.java:1856)
at org.jboss.marshalling.river.RiverUnmarshaller.doInitSerializable(RiverUnmarshaller.java:1769)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadNewObject(RiverUnmarshaller.java:1397)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:275)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:208)
at org.jboss.marshalling.AbstractObjectInput.readObject(AbstractObjectInput.java:41)
at org.jboss.ejb.protocol.remote.EJBServerChannel$RemotingInvocationRequest.getRequestContent(EJBServerChannel.java:805)
at org.jboss.as.ejb3.remote.AssociationImpl.receiveInvocationRequest(AssociationImpl.java:126)
... 7 more
Caused by: an exception which occurred:
in field com.persistence.pojo.Company.Clients
in object com.persistence.pojo.Company@47368172
in object of type com.persistence.pojo.Company
I am using a Wildfly10.x server. The version of hibernatecore is 5.2.17.Final
I am sorry if it is very poorly explained but it is that the project is quite complex, in essence I would need hibernate to map to List object instead of to Persistentbag.
回答1:
The problem here, is that the object you get from hibernate is of some hibernate proxy class, and not your actual entity class. This is normal behaviour for hibernate. This proxy class is autogenerated, and so is it's serialVersionUID.
In general, it is not a good practice to serialize/send entity class objects directly, because of such problems, but also because of problems with lazy initialization and all those connected with having objects bound to entity manager context.
The most common solution is to create "data transport objects" or DTOs which may have the same fields (or very similar - like replace enums with Strings etc, depends on what you need), and nothing else. based on your example, you can have a class like that:
public class CompanyDTO implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private List<ClientDTO> Clients;
//GETTERS&SETTERS
}
(by analogy you need to create ClientDTO class too).
Use this class instead, for outside (where outside is not necessarily remote, just wherever you need to detach from EM context) communication.
You can fill it by hand, or by any other means (like with reflection using BeanUtils, constructor with Company argument which copies properties [this I would not advise, as it interrupts application layer seperation, but for the purpose of this conversation it is a valid way to do that]). The only thing important is that you fill it from within entity manager context
回答2:
In your Client
Entity you need to generate dynamic serialVersionUID, generate one like this
private static final long serialVersionUID = -558553967080513790L;
You can see in this link how to generate the serialVersionUID. For more information see this response.
来源:https://stackoverflow.com/questions/50328616/hibernate-onetomany-relation-is-persistentbag-instead-of-list