Answers:
如果混合使用HQL和本机SQL查询,通常会发生这种情况。在HQL中,Hibernate将您传入的类型映射到数据库可以理解的任何类型。运行本机SQL时,必须自己进行映射。如果您不这样做,则默认的映射是序列化参数并将其发送到数据库(以希望它能理解它)。
Serializable
是两个不同的概念。
根据JPA规范:
如果要通过值将实体实例作为分离的对象(例如,通过远程接口)传递,则实体类必须实现Serializable接口。
“ JSR 220:Enterprise JavaBeansTM,版本3.0 Java Persistence API版本3.0,最终版本,2006年5月2日”
Serializable
这可能会有所帮助,并且在持久性方面比例如保持一致Cloneable
。
Serializable
如果需要通过有线方式传输它们(将它们序列化为其他表示形式),将它们存储在http会话中(然后由servlet容器序列化到硬盘上)等,则需要实体。
仅仅为了持久性,Serializable
就不需要了,至少对于Hibernate而言。但是制作它们是一种最佳实践Serializable
。
为了补充Conor提到JSR-317规范的好答案。通常,EAR项目由EJB模块组成,并且EJB通过远程接口公开。在这种情况下,您需要使实体Bean可序列化,因为它们在远程EJB中进行了聚合,并且可以通过网络进行连接。
没有CDI的JEE6 war项目:可以包含由不可序列化JPA实体支持的EJB lite。
使用CDI的JEE6战争项目:使用会话,应用程序或会话范围的Bean必须可序列化,但是使用请求范围的Bean不必可序列化。因此,底层的JPA实体bean(如果有)将遵循相同的语义。
如果我们只讨论持久性,Serializable
则不是必需的,但是使实体成为最佳实践Serializable
。
如果我们将domain
/ entities
对象直接暴露给表示层,而不是使用DTO
,那么在这种情况下,我们需要实现Serializable
。可以将这些域对象存储在其中HTTPSession
以进行缓存/优化。http会话可以序列化或集群化。而且,在JVM
-instances 之间传输数据也是必需的。
当我们DTO
用来分离持久层和服务层时,将域对象标记为Serializable
适得其反并且会违反“ encapsulation
”。然后,它成为反模式。
主键类必须可序列化。
如果实体实例要作为分离对象远程使用,则实体类必须实现该Serializable
接口。
缓存
另外,如果要实施clustered
第二级,cache
则您的实体必须为serializable
。该标识符必须是Serializable
因为这是JPA要求,因为identifier
可能将用作第二级缓存条目的键。
并且当我们序列化实体时,请确保提供显式serialVersionUID
的私有访问修饰符。因为如果一个serializable
类没有显式声明a serialVersionUID
,那么序列化运行时将根据serialVersionUID
该类的各个方面为该类计算一个默认值,如Java™Object Serialization Specification中所述。默认serialVersionUID
计算对类详细信息高度敏感,类详细信息可能会根据编译器的实现而有所不同,因此可能导致InvalidClassExceptions
反序列化期间发生意外情况。
我相信您的问题与具有未注释的复杂类型(类)的字段有关。在这种情况下,默认处理将把对象以其序列化形式存储在数据库中(这可能不是您想要的目的)。
Class CustomerData {
int getAge();
void setAge(int age);
}
@Entity
Class Customer {
CustomerData getCustomerData();
void setCustomerData(CustomerData data)
}
在上述情况下,CustomerData将以其序列化形式保存在数据库的字节数组字段中。
根据JPA规范,Serializable
仅当实体需要从一个JVM传递到另一个JVM或该实体由有状态会话Bean使用且需要被EJB容器钝化时,才应实现该实体。
如果要通过值将实体实例作为独立对象(例如,通过远程接口)传递,则实体类必须实现该
Serializable
接口。
Hibernate仅要求实体属性为Serializable
,而不要求实体本身。
但是,实施JPA规范后,有关Serializable
实体的所有JPA要求也适用于Hibernate。
根据Tomcat的文档,HttpSession
属性还需要为Serializable
:
只要Apache Tomcat正常关闭并重新启动,或者触发了应用程序重载,标准Manager实施就会尝试将所有当前活动的会话序列化为通过pathname属性定位的磁盘文件。然后,当应用程序重新加载完成时,所有此类保存的会话将被反序列化并激活(假设它们同时没有过期)。
为了成功恢复会话属性的状态,所有这些属性必须实现java.io.Serializable接口。
因此,如果实体存储在中HttpSession
,则应实施Serializable
。
请 说http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_to,它说,java.io.Serializable的实现只需要在JVM实例之间通过IIOP或JRMP(RMI)传输数据。如果是纯Web应用程序,则有时将域对象存储在HTTPSession中,以进行缓存/优化。http会话可以序列化(钝化)或集群化。在这两种情况下,所有内容都必须可序列化。