Hibernate OneToMany 关系是 PersistentBag 而不是 List
Hibernate OneToMany relation is PersistentBag instead of List
我正在用 javafx 开发一个应用程序,它通过 RMI 与 EAR 连接。此 EAR 连接到 SQLServer 数据库并使用休眠映射 POJOS。
这些 POJOS 包含双向 OneToMany 和 ManyToOne 关系。因此,这些关系被映射为 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
}
当我执行这个时,T 是公司:
public default T selectById(Serializable id, Class<T> entityClass,Session session)throws HibernateException {
T obj = null;
obj = session.get(entityClass, id);
return obj;
}
结果是包含所有相应信息的 POJO,但在调试视图中看到这个:
对象已成功实例化并且我的桌面应用程序完美地接收了该对象,但是如果该对象使用接收对象 Company 作为参数的方法再次将其发送到服务器,那么我会遇到此错误。
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(RemoteConnectionChannel.java:430)
at org.jboss.remoting3.EndpointImpl$TrackingExecutor.lambda$execute[=13=](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
我正在使用 Wildfly10.x 服务器。
hibernatecore的版本是5.2.17.Final
很抱歉,如果解释得很差,但项目非常复杂,本质上我需要休眠来映射到 List 对象而不是 Persistentbag。
这里的问题是,您从休眠中获得的对象是某个休眠代理 class,而不是您的实际实体 class。这是休眠的正常行为。
此代理 class 是自动生成的,它的 serialVersionUID 也是自动生成的。
一般来说,直接 serialize/send 实体 class 对象不是一个好的做法,因为这样的问题,也因为惰性初始化和所有与绑定对象相关的问题到实体管理器上下文。
最常见的解决方案是创建 "data transport objects" 或 DTO,它们可能具有相同的字段(或非常相似 - 例如用字符串替换枚举等,取决于您的需要),仅此而已。根据你的例子,你可以有一个 class 这样的:
public class CompanyDTO implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private List<ClientDTO> Clients;
//GETTERS&SETTERS
}
(以此类推,您也需要创建 ClientDTO class)。
改用此 class 进行外部通信(外部不一定是远程的,只是需要与 EM 上下文分离的任何地方)通信。
您可以手动填充它,也可以通过任何其他方式(例如使用 BeanUtils 的反射,带有复制属性的 Company 参数的构造函数[我不建议这样做,因为它会中断应用程序层分离,但为了这次对话是一种有效的方式])。唯一重要的是你从实体管理器上下文中填充它
在您的 Client
实体中您需要生成动态 serialVersionUID,像这样生成一个
private static final long serialVersionUID = -558553967080513790L;
您可以查看in this link如何生成serialVersionUID。
有关详细信息,请参阅此 。
我正在用 javafx 开发一个应用程序,它通过 RMI 与 EAR 连接。此 EAR 连接到 SQLServer 数据库并使用休眠映射 POJOS。
这些 POJOS 包含双向 OneToMany 和 ManyToOne 关系。因此,这些关系被映射为 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
}
当我执行这个时,T 是公司:
public default T selectById(Serializable id, Class<T> entityClass,Session session)throws HibernateException {
T obj = null;
obj = session.get(entityClass, id);
return obj;
}
结果是包含所有相应信息的 POJO,但在调试视图中看到这个:
对象已成功实例化并且我的桌面应用程序完美地接收了该对象,但是如果该对象使用接收对象 Company 作为参数的方法再次将其发送到服务器,那么我会遇到此错误。
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(RemoteConnectionChannel.java:430)
at org.jboss.remoting3.EndpointImpl$TrackingExecutor.lambda$execute[=13=](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
我正在使用 Wildfly10.x 服务器。 hibernatecore的版本是5.2.17.Final
很抱歉,如果解释得很差,但项目非常复杂,本质上我需要休眠来映射到 List 对象而不是 Persistentbag。
这里的问题是,您从休眠中获得的对象是某个休眠代理 class,而不是您的实际实体 class。这是休眠的正常行为。 此代理 class 是自动生成的,它的 serialVersionUID 也是自动生成的。
一般来说,直接 serialize/send 实体 class 对象不是一个好的做法,因为这样的问题,也因为惰性初始化和所有与绑定对象相关的问题到实体管理器上下文。
最常见的解决方案是创建 "data transport objects" 或 DTO,它们可能具有相同的字段(或非常相似 - 例如用字符串替换枚举等,取决于您的需要),仅此而已。根据你的例子,你可以有一个 class 这样的:
public class CompanyDTO implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private List<ClientDTO> Clients;
//GETTERS&SETTERS
}
(以此类推,您也需要创建 ClientDTO class)。
改用此 class 进行外部通信(外部不一定是远程的,只是需要与 EM 上下文分离的任何地方)通信。
您可以手动填充它,也可以通过任何其他方式(例如使用 BeanUtils 的反射,带有复制属性的 Company 参数的构造函数[我不建议这样做,因为它会中断应用程序层分离,但为了这次对话是一种有效的方式])。唯一重要的是你从实体管理器上下文中填充它
在您的 Client
实体中您需要生成动态 serialVersionUID,像这样生成一个
private static final long serialVersionUID = -558553967080513790L;
您可以查看in this link如何生成serialVersionUID。
有关详细信息,请参阅此