何时,为什么JPA实体应该实现Serializable接口?

问题在于标题。 下面我刚刚介绍了一些我的想法和发现。

当我有非常简单的域模型(3表没有任何关系),我所有的实体没有实现Serializable。

但是,当域模型变得更复杂时,我得到了RuntimeException,它说我的一个实体没有实现Serializable。

我使用Hibernate作为JPA实现。

我在想:

  1. 它是供应商特定的要求/行为吗?
  2. 我的序列化实体会发生什么? 它们应该是可序列化的用于存储还是转移?
  3. 在哪一刻,有必要让我的实体可序列化?

这通常发生在混合使用HQL和本机SQL查询的情况下。 在HQL中,Hibernate将您传递的types映射到DB所能理解的任何地方。 当你运行本地SQL时,你必须自己做映射。 如果你不这样做,那么默认的映射就是序列化这个参数并把它发送到数据库(希望它理解它)。

根据JPA规范:

如果一个实体实例被作为一个分离的对象(例如,通过一个远程接口)被传递,实体类必须实现Serializable接口。

“JSR 220:Enterprise JavaBeansTM,版本3.0 Java持久性API版本3.0,最终版本2006年5月2日”

如果你需要将它们通过networking传输(将它们序列化为其他表示forms),将它们存储在http会话中(然后由servlet容器将其序列化到硬盘)等,则需要实体是可Serializable

只是为了持久化,不需要Serializable ,至less在Hibernate中是这样的。 但是使它们可Serializable是一个最佳实践。

为了补充引用JSR-317规范的Conor的好的答案。 通常,EAR项目由EJB模块组成,EJB模块通过远程接口公开。 在这种情况下,您需要使实体bean在远程EJB中聚合时可序列化,并构build为通过networking进行连接。

没有CDI的JEE6战争项目:可以包含由不可序列化的JPA实体支持的EJB Lite。

与CDI的JEE6战争项目: 使用会话,应用程序或会话作用域的bean必须是可序列化的,但使用请求作用域的bean不必是可序列化的。 因此,底层的JPA实体bean(如果有的话)会遵循相同的语义。

我相信你的问题是关于有一个复杂的types(类),这是没有注释的领域。 在这种情况下,默认处理将把数据库中的对象以序列化的forms存储起来(这可能不是你要做的)例如:

 Class CustomerData { int getAge(); void setAge(int age); } @Entity Class Customer { CustomerData getCustomerData(); void setCustomerData(CustomerData data) } 

在上述情况下,CustomerData将以序列化forms保存在数据库中的字节数组字段中。

如果你想序列化它们,类必须实现Serializable。 这与JPA没有直接关系,JPA规范不要求实体是可序列化的。 如果Hibernate真的抱怨这个,我想这是一个Hibernate的bug,但是我想你直接或间接地对实体做了一些其他的事情,这些事情要求它们是可序列化的。

根据hibernate文档 ,在使用@JoinColumn注解时:

它还有一个名为referencedColumnName参数。 该参数声明将用于连接的目标实体中的列。 请注意,在将referencedColumnName用于非主键列时,关联的类必须是Serializable

这也是当你传递一个错误types的ID作为第二个参数到em.find()(即传递实体本身而不是它的ID)时抛出的错误。 我还没有发现它有必要实际声明JPA实体可序列化 – 这是不是真的有必要,除非你使用阿曼描述的referencedColumnName。

远程命中使用邮差或ajax或angularjs等…..,可能会导致重复周期与jackson的StackOverflowexceptionfasterxml.So,最好使用序列化。