代码之家  ›  专栏  ›  技术社区  ›  Sonk4x4

休眠OneToMany关系是PersistentBag而不是List

  •  1
  • Sonk4x4  · 技术社区  · 6 年前

    我正在用javafx开发一个通过RMI与EAR连接的应用程序。此EAR连接到SQLServer DB,并使用hibernate映射POJO。

    这些POJO包含双向的单域和多域关系。因此,这些关系映射为列表。

    公司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   
    
    }
    

    客户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   
    
    }
    

    当我执行此命令时,作为公司:

    public default T selectById(Serializable id, Class<T> entityClass,Session session)throws HibernateException {
        T obj = null;
        obj = session.get(entityClass, id);
        return obj;
    }
    

    结果是包含所有相应信息的POJO,但在调试视图中可以看到:

    screen

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

    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。最终的

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

    2 回复  |  直到 4 年前
        1
  •  2
  •   Jan Ossowski    6 年前

    这里的问题是,从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参数的构造函数[我不建议这样做,因为它会中断应用程序层分离,但就本次对话而言,这是一种有效的方式])。唯一重要的是从实体管理器上下文中填充它

        2
  •  0
  •   Mahmoud    6 年前

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

    private static final long serialVersionUID = -558553967080513790L;
    

    你可以看到 in this link 如何生成serialVersionUID。 有关更多信息,请参见 response