Rom*_*man 128 java orm serialization hibernate jpa
问题出在标题中.下面我刚才描述了我的一些想法和发现.
当我有非常简单的域模型(没有任何关系的3个表)时,我的所有实体都没有实现Serializable.
但是当域模型变得更复杂时,我得到了RuntimeException,它说我的一个实体没有实现Serializable.
我使用Hibernate作为JPA实现.
我想知道:
Con*_*nor 104
根据JPA规范:
如果要通过值将实体实例作为分离对象传递(例如,通过远程接口),则实体类必须实现Serializable接口.
"JSR 220:Enterprise JavaBeansTM,Version 3.0 Java Persistence API Version 3.0,Final Release May 2,2006"
Aar*_*lla 54
如果混合使用HQL和本机SQL查询,通常会发生这种情况.在HQL中,Hibernate将您传入的类型映射到DB理解的任何内容.运行本机SQL时,必须自己进行映射.如果不这样做,那么默认映射是序列化参数并将其发送到数据库(希望它能理解它).
Boz*_*zho 51
Serializable如果需要通过线程传输它们(将它们序列化为其他表示形式),则需要您的实体,将它们存储在http会话中(通过servlet容器将其序列化为硬盘)等.
仅仅为了持久性,Serializable不需要,至少使用Hibernate.但制作它们是最好的做法Serializable.
Vla*_*cea 26
根据 JPA 规范,Serializable仅当实体需要从一个 JVM 传递到另一个 JVM 或实体被需要由 EJB 容器钝化的有状态会话 Bean 使用时,才应实现。
如果实体实例要作为分离对象按值传递(例如,通过远程接口),则实体类必须实现该
Serializable接口。
Hibernate 只要求实体属性是Serializable,而不是实体本身。
然而,实现 JPA 规范,所有关于Serializable实体的 JPA 要求也适用于 Hibernate。
根据Tomcat 文档,HttpSession属性还需要是Serializable:
每当 Apache Tomcat 正常关闭并重新启动时,或者触发应用程序重新加载时,标准管理器实现将尝试将所有当前活动的会话序列化到通过路径名属性定位的磁盘文件。当应用程序重新加载完成时,所有这些保存的会话将被反序列化和激活(假设它们同时没有过期)。
为了成功恢复会话属性的状态,所有这些属性必须实现 java.io.Serializable 接口。
因此,如果实体存储在 中HttpSession,则它应该实现Serializable.
Ank*_*hal 19
如果我们只谈持久化,Serializable是不需要的,但是最好的做法是制作实体Serializable。
如果我们将domain/entities对象直接暴露给表示层,而不是使用DTO,那么我们需要实现Serializable. 可以存储这些域对象以HTTPSession用于缓存/优化目的。http-session 可以被序列化或集群。并且在JVM-instances之间传输数据也需要它。
当我们使用DTO解耦持久层和服务层时,将域对象标记为Serializable会适得其反,并且会违反“ encapsulation”。然后它变成了一种反模式。
主键类必须是可序列化的。
如果将实体实例作为分离对象远程使用,则实体类必须实现该Serializable接口。
缓存
此外,如果您要实现clustered第二级,cache那么您的实体必须是serializable. 标识符必须是Serializable因为这是 JPA 要求,因为它identifier可能用作二级缓存条目的键。
当我们序列化实体时,请确保提供显式serialVersionUID的私有访问修饰符。因为如果一个serializable类没有显式声明serialVersionUID,那么序列化运行时将根据serialVersionUID该类的各个方面计算该类的默认值,如 Java(TM) 对象序列化规范 中所述。默认serialVersionUID计算对可能因编译器实现而异的类细节高度敏感,因此可能会InvalidClassExceptions在反序列化期间导致意外。
为了补充Conor提到JSR-317规范的好答案.通常,EAR项目由EJB模块组成,EJB通过远程接口公开.在这种情况下,您需要使实体bean可序列化,因为它们在远程EJB中聚合并构建为通过网络连接.
没有CDI的JEE6 war项目:可以包含由不可序列化的JPA实体支持的EJB lite.
与CDI的JEE6 war项目:使用会话,应用程序或会话范围的Bean必须是可序列化的,但使用请求范围的bean不必是可序列化的.因此,基础JPA实体bean(如果有的话)将遵循相同的语义.
小智 7
根据hibernate文档,在使用@JoinColumn注释时:
它还有一个名为的参数
referencedColumnName.此参数声明将用于连接的目标实体中的列.请注意,在使用referencedColumnName非主键列时,必须使用关联的类Serializable.
我相信你的问题与一个没有注释的复杂类型(类)的字段有关.在这种情况下,默认处理将在数据库中以序列化形式存储对象(这可能不是你想要做的)示例:
Class CustomerData {
    int getAge();
    void setAge(int age);
}
@Entity
Class Customer {
  CustomerData getCustomerData();
  void setCustomerData(CustomerData data)
}
在上面的例子中,CustomerData将以序列化形式保存在数据库的字节数组字段中.
小智 6
请参阅http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_to 它说,java.io.Serializable 的实现只是在 JVM 实例之间通过 IIOP 或 JRMP (RMI) 传输数据所必需的。在纯 Web 应用程序的情况下,域对象有时存储在 HTTPSession 中以用于缓存/优化目的。http 会话可以序列化(钝化)或集群。在这两种情况下,所有内容都必须是可序列化的。
如果要序列化类,则必须实现 Serializable。这与 JPA 没有直接关系,并且 JPA 规范不要求实体是可序列化的。如果 Hibernate 真的抱怨这个,我想这是一个 Hibernate 错误,但我想你直接或间接地对实体做了一些其他的事情,这需要它们是可序列化的。