Hibernate OneToMany关系是PersistentBag而不是List

时间:2018-05-14 10:55:27

标签: java hibernate ejb wildfly rmi

我正在javafx中开发一个通过RMI与EAR连接的应用程序。此EAR连接到SQLServer DB并使用hibernate映射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包含所有相应的信息,但在调试视图中看到:

https://i.stack.imgur.com/eJm7K.png

该对象已成功实例化,我的桌面应用程序完美地接收了该对象,但如果该对象使用接收对象公司作为参数的方法再次将其发送到服务器,则我会出现此错误。

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

我正在使用Wildfly10.x服务器。 hibernatecore的版本是5.2.17.Final

我很抱歉,如果解释得非常糟糕,但是项目非常复杂,本质上我需要hibernate映射到List对象而不是Persistentbag。

2 个答案:

答案 0 :(得分:1)

这里的问题是,你从hibernate获得的对象是一些hibernate代理类,而不是你的实际实体类。这是hibernate的正常行为。 此代理类是自动生成的,因此它是serialVersionUID。

通常,由于存在这样的问题,直接序列化/发送实体类对象不是一个好习惯,而且还因为延迟初始化的问题以及所有与绑定到实体管理器上下文的对象相关的问题。

最常见的解决方案是创建“数据传输对象”或可能具有相同字段的DTO(或非常相似 - 比如使用字符串替换枚举等,取决于您需要的内容),而不是其他内容。根据您的示例,您可以拥有类似的类:

public class CompanyDTO implements Serializable {

private static final long serialVersionUID = 1L;

private int id;

private List<ClientDTO> Clients;

//GETTERS&SETTERS   

}

(通过类比,你也需要创建ClientDTO类。)

使用此类代替,对于外部(外部不一定是远程的,只需要从EM上下文中分离的任何地方)通信。

你可以手工填写,或者通过任何其他方式填充(比如使用BeanUtils的反射,带有复制属性的Company参数的构造函数[我不建议这样做,因为它会中断应用程序层的分离,但是为了这个对话的目的)这是一种有效的方法])。唯一重要的是你从实体经理上下文中填写它

答案 1 :(得分:0)

在您的Client实体中,您需要生成动态serialVersionUID,生成一个这样的

private static final long serialVersionUID = -558553967080513790L;

您可以看到in this link如何生成serialVersionUID。 有关详细信息,请参阅此response