Quando e por que as entidades JPA devem implementar a interface serializável?

151

A pergunta está no título. Abaixo, acabei de descrever alguns dos meus pensamentos e descobertas.

Quando eu tinha um modelo de domínio muito simples (3 tabelas sem nenhuma relação), todas as minhas entidades NÃO implementavam Serializable.

Mas quando o modelo de domínio se tornou mais complexo, obtive o RuntimeException, que dizia que uma das minhas entidades não implementava Serializable.

Eu uso o Hibernate como uma implementação JPA.

Eu me pergunto:

  1. É um requisito / comportamento específico do fornecedor?
  2. O que acontece com minhas entidades serializáveis? Eles devem ser serializáveis ​​para armazenamento ou transferência?
  3. Em que momento se torna necessário tornar minha entidade serializável?
romano
fonte

Respostas:

59

Isso geralmente acontece se você combinar consultas HQL e SQL nativas. No HQL, o Hibernate mapeia os tipos que você passa para o que o banco de dados entende. Ao executar o SQL nativo, você mesmo deve fazer o mapeamento. Caso contrário, o mapeamento padrão é serializar o parâmetro e enviá-lo ao banco de dados (na esperança de que ele o entenda).

Aaron Digulla
fonte
Isso não explica por que apenas "talvez como" See resposta abaixo de Bozho
chrips
essa entidade média será salva no banco de dados sem implementar a interface serializável?
Hanumantha_3048092
@ Hanumantha_3048092 Sim. Mapeamento de entidade e Serializablesão dois conceitos diferentes.
Aaron Digulla 07/01
@AaronDigulla Você pode explicá-lo com um exemplo ou pseudo-código.
sdindiver 8/04
110

De acordo com a JPA Spec:

Se uma instância de entidade deve ser passada por valor como um objeto desanexado (por exemplo, por meio de uma interface remota), a classe de entidade deve implementar a interface Serializable.

"JSR 220: Enterprise JavaBeansTM, Versão 3.0 Java Persistence API Versão 3.0, Versão final em 2 de maio de 2006"

Conor
fonte
14
(+1) olhando para a especificação é sempre frutífera
Bozho
20
Não vejo por que isso tem tantos votos positivos. O OP diz que não era necessário quando o modelo era mais simples. Enviar os objetos remotamente via serialização Java sempre exigiria que os objetos fossem serializáveis, independentemente de sua complexidade. Obviamente, este não é o caso de uso do OP.
22615 Robin
Não tenho muita certeza sobre o hibernate, mas com outros provedores de JPA, existem operações que exigem que o provedor faça uma cópia de uma entidade (objeto). Serializablepoderia ser útil com isso, e no contexto de persistência mais consistente do que Cloneablepor exemplo.
21715 JimmyBoi
Esta resposta é apenas um despejo de informações e não ajuda ninguém a entender o porquê.
Chrips # 21/19
59

Você precisa de suas entidades Serializablese precisar transferi-las por fio (serialize-as para alguma outra representação), armazene-as na sessão http (que por sua vez é serializada em disco rígido pelo contêiner do servlet), etc.

Apenas por uma questão de persistência, Serializablenão é necessário, pelo menos com o Hibernate. Mas é uma prática recomendada fazê-los Serializable.

Bozho
fonte
2
Não sei, talvez minhas entidades estejam sendo transferidas implicitamente para algum lugar. Eu uso o hibernate + spring + jsf e o Tomcat. Onde nesta cadeia a transferência pode ocorrer?
romano
@Roman, por exemplo, o usuário atual (que pode ser uma entidade) e todas as suas entidades relacionadas podem terminar na sessão, que, como diz Bozho, pode ser serializada em disco pelo contêiner do servlet.
OrangeDog
Esta é a melhor resposta "por que e quando"! Claro! Obrigado
chrips
13

De acordo com os documentos do hibernate , ao usar a anotação @JoinColumn:

Tem mais um parâmetro nomeado referencedColumnName. Este parâmetro declara a coluna na entidade de destino que será usada para a associação. Observe que ao usar referencedColumnNameuma coluna de chave não primária, a classe associada deve ser Serializable.

aman maharjan
fonte
8

Para complementar a boa resposta de Conor, que se referiu às especificações JSR-317. Normalmente, os projetos EAR consistem em um módulo EJB com os EJBs expostos por meio de uma interface remota. Nesse caso, você precisa tornar seus beans de entidade serializáveis, pois eles são agregados no EJB remoto e construídos para serem conectados através da rede.

Um projeto de guerra JEE6 sem CDI: pode conter EJB lite apoiado por entidades JPA não serializáveis.

Um projeto de guerra JEE6 com CDI: Beans que usam escopo de sessão, aplicativo ou conversa devem ser serializáveis, mas os beans que usam escopo de solicitação não precisam ser serializáveis. Assim, os beans de entidade JPA subjacentes - se houver - seguiriam a mesma semântica.

Sym-Sym
fonte
7

Se falamos apenas de persistência, Serializablenão é necessário. Mas é uma prática recomendada criar as entidades Serializable.

Se estamos expondo domain/ entitiesobjetos diretamente expostos à camada de apresentação, em vez de usar DTO, nesse caso, precisamos implementar Serializable. Esses objetos de domínio podem ser armazenados HTTPSessionpara fins de cache / otimização. Uma sessão http pode ser serializada ou agrupada. E também é necessário para transferir dados entre JVMinstâncias.

Quando usamos DTOpara dissociar a camada de persistência e a camada de serviço, marcar os objetos do domínio como Serializablecontraproducente e violar a "encapsulation ”. Então se torna um anti-padrão.

Identificadores compostos

A classe de chave primária deve ser serializável.

Modelos POJO

Se uma instância de entidade deve ser usada remotamente como um objeto desanexado, a classe de entidade deve implementar a Serializableinterface.

Cache
Além disso, se você estiver implementando um clusteredsegundo nível cache, suas entidades deverão estar serializable. O identificador deve ser Serializableporque esse é um requisito de JPA, pois identifierpode ser usado como a chave para uma entrada de cache de segundo nível.

E quando serializamos entidades, certifique-se de fornecer explícito serialVersionUIDo modificador de acesso privado. Porque se umserializable classe não declarar explicitamente a serialVersionUID, o tempo de execução da serialização calculará um serialVersionUIDvalor padrão para essa classe com base em vários aspectos da classe, conforme descrito em Java (TM) Object Serialization Specification. A serialVersionUIDcomputação padrão é altamente sensível aos detalhes da classe que podem variar dependendo das implementações do compilador e, portanto, podem resultar em inesperado InvalidClassExceptionsdurante a desserialização.

Ankur Singhal
fonte
6

Acredito que seu problema está relacionado a ter um campo de um tipo complexo (classe) que não está anotado. Nesses casos, o tratamento padrão armazenará o objeto em sua forma serializada no banco de dados (o que provavelmente não é o que você pretendia fazer) Exemplo:

Class CustomerData {
    int getAge();
    void setAge(int age);
}

@Entity
Class Customer {
  CustomerData getCustomerData();
  void setCustomerData(CustomerData data)
}

No caso acima, os Dados do Cliente serão salvos em um campo de matriz de bytes no banco de dados em seu formato serializado.

Avner Levy
fonte
5

Especificação JPA

De acordo com a especificação da JPA, uma entidade deve implementar Serializableapenas se precisar ser transmitida de uma JVM para outra ou se a entidade for usada por um Bean de Sessão com Estado, que precisa ser passivado pelo contêiner EJB.

Se uma instância de entidade deve ser passada por valor como um objeto desanexado (por exemplo, através de uma interface remota), a classe de entidade deve implementar a Serializableinterface.

Hibernate

O Hibernate requer apenas que os atributos da entidade sejam Serializable , mas não a própria entidade.

No entanto, implementando a especificação da JPA, todos os requisitos da JPA relativos a Serializable entidades também se aplicam ao Hibernate.

Tomcat

De acordo com a documentação do Tomcat , os HttpSessionatributos também precisam ser Serializable:

Sempre que o Apache Tomcat for desligado normalmente e reiniciado, ou quando uma recarga de aplicativo for acionada, a implementação padrão do Gerenciador tentará serializar todas as sessões ativas no momento em um arquivo de disco localizado através do atributo nome do caminho. Todas essas sessões salvas serão desserializadas e ativadas (supondo que não tenham expirado nesse período) quando a recarga do aplicativo for concluída.

Para restaurar com êxito o estado dos atributos da sessão, todos esses atributos DEVEM implementar a interface java.io.Serializable.

Portanto, se a entidade estiver armazenada no HttpSession, ela deve implementar Serializable.

Vlad Mihalcea
fonte
4

As classes devem implementar Serializable se você deseja serializá-las. Isso não está diretamente relacionado à JPA e a especificação da JPA não exige que as entidades sejam serializáveis. Se o Hibernate realmente reclamar disso, suponho que seja um bug do Hibernate, mas suponho que você, direta ou indiretamente, esteja fazendo outra coisa com as entidades, o que exige que elas sejam serializáveis.

jarnbjo
fonte
3

Consulte http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_para ele diz: A implementação do java.io.Serializable é simplesmente necessária para a transferência de dados via IIOP ou JRMP (RMI) entre instâncias da JVM. No caso de um aplicativo Web puro, os objetos do domínio às vezes são armazenados no HTTPSession para fins de cache / otimização. Uma sessão http pode ser serializada (passivação) ou em cluster. Nos dois casos, todo o conteúdo deve ser serializável.

Arun K
fonte
1

hit remoto usando carteiro ou ajax ou js angulares etc ....., pode causar o ciclo de repetição com a exceção StackOverflow com o Jackson mais rápidoxml.Então, é melhor usar o serializador.

tâmil
fonte
1
  1. Em que momento se torna necessário tornar minha entidade serializável?

A implementação do ehcache com o diskstore como cache de segundo nível (isto é, usando @Cacheableanotação na entidade ou método de repositório / serviço) requer Serializable, caso contrário, o cache falhará ( NotSerializableException) ao gravar a entidade no cache do disco.

Michal
fonte
0

Este também é o erro que ocorre quando você passa um ID digitado incorretamente como o segundo parâmetro para algo como em.find () (ou seja, passar a própria entidade em vez de seu ID). Ainda não achei necessário declarar serialmente entidades JPA serializáveis ​​- não é realmente necessário, a menos que você esteja usando referencedColumnName conforme descrito por aman.

Amalgovinus
fonte
0

quando entidades JPA são usadas como parâmetros ou retornam valores pelas operações EJB remotas

SAR
fonte