SlideShare uma empresa Scribd logo
1 de 5
Entenda o ciclo de vida das entidades JPA
Para quem trabalha com a especificação JPA (Java Persistence API), é muito importante
dominar o ciclo de vida das entidades e o estado que cada uma pode assumir. Neste artigo,
explicaremos esses conceitos para evitar que você cometa erros que podem gerar
comportamentos indesejados (e perigosos) no sistema.
Para explicarmos os conceitos, vamos considerar a entidade abaixo:
@Entity
public class Produto {
@Id
@GeneratedValue
private Long id;
private String nome;
//métodos getters e setters
}
e vamos considerar, também, o seguinte esquema:
Estado Transient (Transitório)
Quando damos um new em uma entidade anotada com @Entity (objeto-entidade), ela ainda
não é reconhecida pelo JPA porque ela nunca passou pelo gerenciador de
persistência EntityManager. A entidade também não possui um ID e, provavelmente, não existe
no banco de dados. Neste caso, não há garantia alguma de que os dados existentes no objeto-
entidade serão persistidos no banco quando o processamento do sistema terminar. Este
estado é conhecido como Transient.
Abaixo apresentamos um código onde o objeto-entidade (variável "p") está Transient. Nada
ocorre ao final da execução desse código.
EntityManager em = //Obtém o entity manager
em.getTransaction().begin();
//Estado Transient
Produto p = new Produto();
p.setNome("Macarrão");
em.getTransaction().commit();
Graficamente, podemos representar esse estado da seguinte forma:
Estado Managed (Gerenciado)
O estado Managed é o estado onde o JPA reconhece a existência de um objeto-entidade e,
consequentemente, o JPA garante que esse objeto terá representação idêntica no banco de
dados. Isso significa que qualquer alteração que você fizer nesse objeto será automaticamente
persistido no banco. Um detalhe importante: a fluxo de sincronização parte sempre do objeto
para o banco de dados, nunca ao contrário. Isso significa que o JPA não detecta alterações
realizadas diretamente no banco de dados.
De acordo com a figura sobre o ciclo de vida das entidades (1ª figura), para que um objeto-
entidade vá para o estado Managed, os métodos persist, merge, find ou getReference devem
ser invocados para avisar aoEntityManager sobre a existência do objeto e para que este seja
controlado por aquele.
Abaixo temos um código que coloca a variável "p" sob gestão do EntityManager.
EntityManager em = //Obtém o entity manager
em.getTransaction().begin();
//Estado Transient
Produto p = new Produto();
p.setNome("Macarrão");
//Estado Managed
em.persist(p); //momento 1
p.setNome("Macarrão Integral"); //momento 2
em.getTransaction().commit(); //momento 3
No "momento 1" (execução do método persist), o JPA irá realizar um INSERT no banco de
dados com o nome "Macarrão", irá recuperar o ID gerado pelo banco (por causa da
anotação @GeneratedValue), irá atribuir esse valor à propriedade anotada com
o @Id (propriedade "id") e irá colocar o objeto "p" sob gestão do EntityManager (o estado muda
para Managed).
No "momento 2" (apenas a execução de um set), houve uma alteração na propriedade nome.
Como o objeto já está sendo gerenciado pelo EntityManager, o objeto é marcado como "sujo"
para ser atualizado futuramente. Observe que não é necessário um novo persist
(ou merge) porque o objeto já está sendo gerenciado pelo EntityManager.
No "momento 3" ocorre o commit. O JPA dispara um UPDATE no banco de dados para manter
uma representação idêntica no banco - o nome do produto passa a ser "Macarrão Integral".
É importante ressaltar que a execução do persist dispara, imediatamente, um INSERT para o
banco de dados (ocorre na hora). Por outro lado, por questões de economia, quando um objeto
gerenciado sofre uma alteração em uma propriedade (um set), o UPDATE para o banco de
dados é adiado até a execução de umcommit (o UPDATE não ocorre na hora).
Graficamente, podemos representar o "momento 1", o "momento 2" e o "momento 3" da
seguinte forma:
Abaixo apresentamos um outro exemplo de código que obtém um Produto através do
método find e atualiza o seu nome para "Macarrão de Ovos". Observe que, após a alteração do
nome do produto, não é necessário fazer uma chamada merge para que os dados sejam
persistidos porque o método find já coloca o objeto-entidade "p" em estado gerenciado.
Novamente, o JPA irá garantir uma fiel representação desse objeto no banco e realiza um
UPDATE automaticamente após o commit.
EntityManager em = //Obtém o entity manager
em.getTransaction().begin();
//Estado Managed
Produto p = em.find(Produto.class, 1);
p.setNome("Macarrão de Ovos");
em.getTransaction().commit();
A característica do estado Managed é que o objeto-entidade possui um ID, é conhecido
pelo EntityManagere possui a informação no banco de dados.
Estado Detached (Destacado)
Imagine que você tenha uma funcionalidade com várias telas organizadas em abas
(estilo Wizard) e que o usuário precisa acrescentar dados em todas elas até uma confirmação
final. Imagine também que você tenha um objeto-entidade gerenciado que esteja sendo
utilizado nessas abas. Durante a navegação, esse objeto-entidade sofre vários sets em seus
atributos (e cada aba tem um commit) até a confirmação final (última aba). Como o objeto está
gerenciado pelo EntityManager, cada tela concluída irá disparar um UPDATE no banco,
aumentando a quantidade de round trips para o banco e prejudicando o desempenho do
sistema.
O objetivo do método detach é retirar, temporariamente, o objeto-entidade gerenciado para um
estado não gerenciado para que problemas descritos no cenário acima não ocorram. A
característica desse estado é que os objetos-gerenciados possuem um ID, provavelmente
possui a informação no banco, mas não está sendo gerenciado pelo EntityManager. Se você
também dar um new em um objeto-entidade e atribuir manualmente um ID a ele, ele também
torna-se um objeto destacado.
Abaixo temos um código que retira a variável "p" da gestão do EntityManager.
EntityManager em = //Obtém o entity manager
em.getTransaction().begin();
//Estado Managed
Produto p = em.find(Produto.class, 1);
//Estado Detached
em.detach(p);
p.setNome("Macarrão Instantâneo");
em.getTransaction().commit();
Graficamente, podemos representar o resultado do código acima da seguinte forma:
Quando o usuário finalizar todo o processo clicando no botão salvar da última aba, desejamos
sincronizar as diferenças de "p" com o banco de dados chamando o método merge. Aqui tem
uma pegadinha que devemos tomar cuidado: ao executar esse método, o JPA faz um SELECT
no banco, cria um outro objeto-entidade chamada "p1" com os valores encontrados no banco;
coloca esse objeto em estado gerenciado (Managed); atribui as diferença de valores de "p" a
"p1" e; como "p1" está gerenciado e houve alteração de propriedade, ele torna-se "sujo" para
um UPDATE futuro (após um commit). Observe que "p" continua destacado e qualquer
alteração que você realizar sobre ele não surtirá efeito no banco. Observe o código abaixo:
EntityManager em = //Obtém o entity manager
em.getTransaction().begin();
//Estado Managed
Produto p = em.find(Produto.class, 1);
//Estado Detached
em.detach(p);
p.setNome("Macarrão Instantâneo");
//Momento 1 e 2.
em.merge(p);
//Momento 3.
p.setNome("Macarrão de Microondas");
//Momento 4
em.getTransaction().commit();
Veja abaixo a explicação dos momentos 1, 2, 3 e 4:
É um erro comum o programador achar que, após um merge, o objeto-entidade volta ao estado
gerenciado. Como consequência, as informações inseridas no objeto-entidade após
o merge serão perdidas, como ocorreu com a informação "Macarrão de Microondas". Para
resolver esse problema, devemos atribuir a "p" o resultado o método merge, que retorna a
instância "p1" gerenciada e recém criada. Segue o código correto:
EntityManager em = //Obtém o entity manager
em.getTransaction().begin();
//Estado Managed
Produto p = em.find(Produto.class, 1);
//Estado Detached
em.detach(p);
p.setNome("Macarrão Instantâneo");
//Dados sincronizados no banco.
p = em.merge(p);
//Agora "p" está gerenciado (Managed)
e a alteração abaixo é salva no banco
p.setNome("Macarrão de Microondas");
em.getTransaction().commit();
Há também os métodos clear e close que também colocam os objetos-entidades em
estado Detached. A diferença entre eles é que o clear coloca todos os objetos-entidades
gerenciados pelo EntityManager para o estado Detached sem matar o gerenciador (em outras
palavras, podemos dizer que o clear "bota todo mundo pra fora" sem fechar a firma). O
método close, além de "botar todo mundo pra fora", ele mata oEntityManager (a firma fecha).
Estado Removed (Removido)
O último estado, Removed, é quando queremos excluir um objeto-entidade do banco. A
característica de um objeto removido é que ele possui um ID, não está mais gerenciado
pelo EntityManager e não está mais no banco de dados. Observe na figura sobre o ciclo de
vida das entidades (1ª figura) que o objeto-entidade só pode ser removido se estiver, primeiro,
em um estado Gerenciado.
Abaixo ocorre um erro se você tentar executar o seguinte código:
EntityManager em = //Obtém o entity manager
em.getTransaction().begin();
//Estado Transient
Produto p = new Produto();
//Estado Detached
p.setId(1);
em.remove(p); //ERRO: "Detached" não passa para "Removed".
em.getTransaction().commit();
Por fim, o correto deveria ser:
EntityManager em = //Obtém o entity manager
em.getTransaction().begin();
//Estado Transient
Produto p = new Produto();
//Estado Detached
p.setId(1);
em.remove(em.merge(p)); //OK: merge coloca "p" em estado "Managed".
em.getTransaction().commit();
Concluímos nosso primeiro estudo sobre Persistência considerando a especificação JPA e
esperamos que o assunto abordado facilite o seu dia-a-dia nesse complexo mundo Object-
Relational Mapping (ORM).

Mais conteúdo relacionado

Mais procurados

API de segurança do Java EE 8
API de segurança do Java EE 8API de segurança do Java EE 8
API de segurança do Java EE 8Helder da Rocha
 
Java introdução ao java
Java   introdução ao javaJava   introdução ao java
Java introdução ao javaArmando Daniel
 
Exercicios Filas (Queues) - Estruturas de dados e algoritmos com Java
Exercicios Filas (Queues) - Estruturas de dados e algoritmos com JavaExercicios Filas (Queues) - Estruturas de dados e algoritmos com Java
Exercicios Filas (Queues) - Estruturas de dados e algoritmos com JavaLoiane Groner
 
Arrays (vetores) em Java
Arrays (vetores) em JavaArrays (vetores) em Java
Arrays (vetores) em JavaDaniel Brandão
 
Introdução à Programação Web com Angular
Introdução à Programação Web com AngularIntrodução à Programação Web com Angular
Introdução à Programação Web com AngularElmano Cavalcanti
 
Java: Excecoes e Tratamento de Erros
Java: Excecoes e Tratamento de ErrosJava: Excecoes e Tratamento de Erros
Java: Excecoes e Tratamento de ErrosArthur Emanuel
 
[Curso Java Basico] Exercicios Aula 19
[Curso Java Basico] Exercicios Aula 19[Curso Java Basico] Exercicios Aula 19
[Curso Java Basico] Exercicios Aula 19Loiane Groner
 
Aula 1 - Introdução a POO
Aula 1 -  Introdução a POOAula 1 -  Introdução a POO
Aula 1 - Introdução a POODaniel Brandão
 
Programação orientada a objetos
Programação orientada a objetosProgramação orientada a objetos
Programação orientada a objetosCleyton Ferrari
 
Java: Estruturas de Repetição
Java: Estruturas de RepetiçãoJava: Estruturas de Repetição
Java: Estruturas de RepetiçãoArthur Emanuel
 
Curso de Enterprise JavaBeans (EJB) (JavaEE 7)
Curso de Enterprise JavaBeans (EJB) (JavaEE 7)Curso de Enterprise JavaBeans (EJB) (JavaEE 7)
Curso de Enterprise JavaBeans (EJB) (JavaEE 7)Helder da Rocha
 
Exercícios - Herança - Java
Exercícios - Herança - JavaExercícios - Herança - Java
Exercícios - Herança - JavaArthur Emanuel
 
[Curso Java Basico] Aula 20: Arrays multidimensionais - Matrizes
[Curso Java Basico] Aula 20: Arrays multidimensionais - Matrizes[Curso Java Basico] Aula 20: Arrays multidimensionais - Matrizes
[Curso Java Basico] Aula 20: Arrays multidimensionais - MatrizesLoiane Groner
 
Java Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepJava Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepGuo Albert
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJosé Paumard
 
Codigo limpo: Nomes Significativos Cap 2
Codigo limpo:  Nomes Significativos Cap 2Codigo limpo:  Nomes Significativos Cap 2
Codigo limpo: Nomes Significativos Cap 2Inael Rodrigues
 

Mais procurados (20)

Minicurso Linux
Minicurso Linux Minicurso Linux
Minicurso Linux
 
API de segurança do Java EE 8
API de segurança do Java EE 8API de segurança do Java EE 8
API de segurança do Java EE 8
 
Java introdução ao java
Java   introdução ao javaJava   introdução ao java
Java introdução ao java
 
Aula javascript
Aula  javascriptAula  javascript
Aula javascript
 
Exercicios Filas (Queues) - Estruturas de dados e algoritmos com Java
Exercicios Filas (Queues) - Estruturas de dados e algoritmos com JavaExercicios Filas (Queues) - Estruturas de dados e algoritmos com Java
Exercicios Filas (Queues) - Estruturas de dados e algoritmos com Java
 
Arrays (vetores) em Java
Arrays (vetores) em JavaArrays (vetores) em Java
Arrays (vetores) em Java
 
Introdução à Programação Web com Angular
Introdução à Programação Web com AngularIntrodução à Programação Web com Angular
Introdução à Programação Web com Angular
 
Java: Excecoes e Tratamento de Erros
Java: Excecoes e Tratamento de ErrosJava: Excecoes e Tratamento de Erros
Java: Excecoes e Tratamento de Erros
 
[Curso Java Basico] Exercicios Aula 19
[Curso Java Basico] Exercicios Aula 19[Curso Java Basico] Exercicios Aula 19
[Curso Java Basico] Exercicios Aula 19
 
Aula 1 - Introdução a POO
Aula 1 -  Introdução a POOAula 1 -  Introdução a POO
Aula 1 - Introdução a POO
 
Programação orientada a objetos
Programação orientada a objetosProgramação orientada a objetos
Programação orientada a objetos
 
Java: Estruturas de Repetição
Java: Estruturas de RepetiçãoJava: Estruturas de Repetição
Java: Estruturas de Repetição
 
Curso de Enterprise JavaBeans (EJB) (JavaEE 7)
Curso de Enterprise JavaBeans (EJB) (JavaEE 7)Curso de Enterprise JavaBeans (EJB) (JavaEE 7)
Curso de Enterprise JavaBeans (EJB) (JavaEE 7)
 
Exercícios - Herança - Java
Exercícios - Herança - JavaExercícios - Herança - Java
Exercícios - Herança - Java
 
[Curso Java Basico] Aula 20: Arrays multidimensionais - Matrizes
[Curso Java Basico] Aula 20: Arrays multidimensionais - Matrizes[Curso Java Basico] Aula 20: Arrays multidimensionais - Matrizes
[Curso Java Basico] Aula 20: Arrays multidimensionais - Matrizes
 
Java Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepJava Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By Step
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patterns
 
Codigo limpo: Nomes Significativos Cap 2
Codigo limpo:  Nomes Significativos Cap 2Codigo limpo:  Nomes Significativos Cap 2
Codigo limpo: Nomes Significativos Cap 2
 
Apostila java completo
Apostila java completoApostila java completo
Apostila java completo
 
POO - 14 - Vetores
POO - 14 - VetoresPOO - 14 - Vetores
POO - 14 - Vetores
 

Semelhante a Ciclo de vida das entidades JPA: entenda os estados transient, managed, detached e removed

Persistência com JPA e Hibernate
Persistência com JPA e HibernatePersistência com JPA e Hibernate
Persistência com JPA e HibernateFernando Oliveira
 
Aula 15 e 16 - Navegação - Activities e Fragments.pptx.pdf
Aula 15 e 16 - Navegação - Activities e Fragments.pptx.pdfAula 15 e 16 - Navegação - Activities e Fragments.pptx.pdf
Aula 15 e 16 - Navegação - Activities e Fragments.pptx.pdfnosbisantos
 
Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0
Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0
Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0Elvis Rocha
 
Java Desktop
Java DesktopJava Desktop
Java Desktopciceroclc
 
Curso java 03 - métodos e parâmetros
Curso java   03 - métodos e parâmetrosCurso java   03 - métodos e parâmetros
Curso java 03 - métodos e parâmetrosMaurício Linhares
 
WEB 2 - Aula 01 - 02.08
WEB 2 - Aula 01 - 02.08WEB 2 - Aula 01 - 02.08
WEB 2 - Aula 01 - 02.08Gilson Silva
 
Teste de Integracao com DbUnit e JStryker
Teste de Integracao com DbUnit e JStrykerTeste de Integracao com DbUnit e JStryker
Teste de Integracao com DbUnit e JStrykerWashington Botelho
 
Como conectar programas em linguagem java a bases de dados
Como conectar programas em linguagem java  a bases de dadosComo conectar programas em linguagem java  a bases de dados
Como conectar programas em linguagem java a bases de dadosHenrique Fernandes
 
Java interface gráfica swing
Java   interface gráfica swingJava   interface gráfica swing
Java interface gráfica swingArmando Daniel
 
Introdução à análise orientada a objetos parte 2
Introdução à análise orientada a objetos parte 2Introdução à análise orientada a objetos parte 2
Introdução à análise orientada a objetos parte 2irenescotolo
 
Atividades e Intenções (Android)
Atividades e Intenções (Android)Atividades e Intenções (Android)
Atividades e Intenções (Android)Natanael Fonseca
 
Apostila Completa de Visual Basic
Apostila Completa de Visual BasicApostila Completa de Visual Basic
Apostila Completa de Visual BasicMarcos Paulo
 
Regras de Produção: o Motor de Inferência JESS
Regras de Produção:o Motor de Inferência JESSRegras de Produção:o Motor de Inferência JESS
Regras de Produção: o Motor de Inferência JESSelliando dias
 

Semelhante a Ciclo de vida das entidades JPA: entenda os estados transient, managed, detached e removed (20)

Persistência com JPA e Hibernate
Persistência com JPA e HibernatePersistência com JPA e Hibernate
Persistência com JPA e Hibernate
 
Aula 15 e 16 - Navegação - Activities e Fragments.pptx.pdf
Aula 15 e 16 - Navegação - Activities e Fragments.pptx.pdfAula 15 e 16 - Navegação - Activities e Fragments.pptx.pdf
Aula 15 e 16 - Navegação - Activities e Fragments.pptx.pdf
 
Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0
Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0
Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0
 
JPA - Java Persistence API
JPA - Java Persistence APIJPA - Java Persistence API
JPA - Java Persistence API
 
Java Desktop
Java DesktopJava Desktop
Java Desktop
 
Curso java 03 - métodos e parâmetros
Curso java   03 - métodos e parâmetrosCurso java   03 - métodos e parâmetros
Curso java 03 - métodos e parâmetros
 
WEB 2 - Aula 01 - 02.08
WEB 2 - Aula 01 - 02.08WEB 2 - Aula 01 - 02.08
WEB 2 - Aula 01 - 02.08
 
Teste de Integracao com DbUnit e JStryker
Teste de Integracao com DbUnit e JStrykerTeste de Integracao com DbUnit e JStryker
Teste de Integracao com DbUnit e JStryker
 
Course Hibernate 2008
Course Hibernate 2008Course Hibernate 2008
Course Hibernate 2008
 
CURSO JAVA 02
CURSO JAVA 02CURSO JAVA 02
CURSO JAVA 02
 
Como conectar programas em linguagem java a bases de dados
Como conectar programas em linguagem java  a bases de dadosComo conectar programas em linguagem java  a bases de dados
Como conectar programas em linguagem java a bases de dados
 
Java interface gráfica swing
Java   interface gráfica swingJava   interface gráfica swing
Java interface gráfica swing
 
Introdução à análise orientada a objetos parte 2
Introdução à análise orientada a objetos parte 2Introdução à análise orientada a objetos parte 2
Introdução à análise orientada a objetos parte 2
 
Persistência JPA
Persistência JPAPersistência JPA
Persistência JPA
 
Jdbc e hibernate
Jdbc e hibernateJdbc e hibernate
Jdbc e hibernate
 
Padrão Iterator
Padrão IteratorPadrão Iterator
Padrão Iterator
 
Javascript avançado
Javascript avançadoJavascript avançado
Javascript avançado
 
Atividades e Intenções (Android)
Atividades e Intenções (Android)Atividades e Intenções (Android)
Atividades e Intenções (Android)
 
Apostila Completa de Visual Basic
Apostila Completa de Visual BasicApostila Completa de Visual Basic
Apostila Completa de Visual Basic
 
Regras de Produção: o Motor de Inferência JESS
Regras de Produção:o Motor de Inferência JESSRegras de Produção:o Motor de Inferência JESS
Regras de Produção: o Motor de Inferência JESS
 

Mais de MoisesInacio

Mq conceitos melhores_praticas_parte_ii
Mq conceitos melhores_praticas_parte_iiMq conceitos melhores_praticas_parte_ii
Mq conceitos melhores_praticas_parte_iiMoisesInacio
 
Mq conceitos melhores_praticas
Mq conceitos melhores_praticasMq conceitos melhores_praticas
Mq conceitos melhores_praticasMoisesInacio
 
Escrever e ler arquivos com java
Escrever e ler arquivos com javaEscrever e ler arquivos com java
Escrever e ler arquivos com javaMoisesInacio
 
Datacenter virtual-guia
Datacenter virtual-guiaDatacenter virtual-guia
Datacenter virtual-guiaMoisesInacio
 
Algaworks livro-spring-boot-v3.0
Algaworks livro-spring-boot-v3.0Algaworks livro-spring-boot-v3.0
Algaworks livro-spring-boot-v3.0MoisesInacio
 
Algaworks ebook-java-ee-7-com-jsf-primefaces-e-cdi-2a-edicao-20150228
Algaworks ebook-java-ee-7-com-jsf-primefaces-e-cdi-2a-edicao-20150228Algaworks ebook-java-ee-7-com-jsf-primefaces-e-cdi-2a-edicao-20150228
Algaworks ebook-java-ee-7-com-jsf-primefaces-e-cdi-2a-edicao-20150228MoisesInacio
 
Jaxrs 1.0-final-spec
Jaxrs 1.0-final-specJaxrs 1.0-final-spec
Jaxrs 1.0-final-specMoisesInacio
 

Mais de MoisesInacio (9)

Mq conceitos melhores_praticas_parte_ii
Mq conceitos melhores_praticas_parte_iiMq conceitos melhores_praticas_parte_ii
Mq conceitos melhores_praticas_parte_ii
 
Mq conceitos melhores_praticas
Mq conceitos melhores_praticasMq conceitos melhores_praticas
Mq conceitos melhores_praticas
 
Escrever e ler arquivos com java
Escrever e ler arquivos com javaEscrever e ler arquivos com java
Escrever e ler arquivos com java
 
Datacenter virtual-guia
Datacenter virtual-guiaDatacenter virtual-guia
Datacenter virtual-guia
 
Algaworks livro-spring-boot-v3.0
Algaworks livro-spring-boot-v3.0Algaworks livro-spring-boot-v3.0
Algaworks livro-spring-boot-v3.0
 
Algaworks ebook-java-ee-7-com-jsf-primefaces-e-cdi-2a-edicao-20150228
Algaworks ebook-java-ee-7-com-jsf-primefaces-e-cdi-2a-edicao-20150228Algaworks ebook-java-ee-7-com-jsf-primefaces-e-cdi-2a-edicao-20150228
Algaworks ebook-java-ee-7-com-jsf-primefaces-e-cdi-2a-edicao-20150228
 
J query
J queryJ query
J query
 
Artigoajax
ArtigoajaxArtigoajax
Artigoajax
 
Jaxrs 1.0-final-spec
Jaxrs 1.0-final-specJaxrs 1.0-final-spec
Jaxrs 1.0-final-spec
 

Ciclo de vida das entidades JPA: entenda os estados transient, managed, detached e removed

  • 1. Entenda o ciclo de vida das entidades JPA Para quem trabalha com a especificação JPA (Java Persistence API), é muito importante dominar o ciclo de vida das entidades e o estado que cada uma pode assumir. Neste artigo, explicaremos esses conceitos para evitar que você cometa erros que podem gerar comportamentos indesejados (e perigosos) no sistema. Para explicarmos os conceitos, vamos considerar a entidade abaixo: @Entity public class Produto { @Id @GeneratedValue private Long id; private String nome; //métodos getters e setters } e vamos considerar, também, o seguinte esquema: Estado Transient (Transitório) Quando damos um new em uma entidade anotada com @Entity (objeto-entidade), ela ainda não é reconhecida pelo JPA porque ela nunca passou pelo gerenciador de persistência EntityManager. A entidade também não possui um ID e, provavelmente, não existe no banco de dados. Neste caso, não há garantia alguma de que os dados existentes no objeto- entidade serão persistidos no banco quando o processamento do sistema terminar. Este estado é conhecido como Transient. Abaixo apresentamos um código onde o objeto-entidade (variável "p") está Transient. Nada ocorre ao final da execução desse código. EntityManager em = //Obtém o entity manager em.getTransaction().begin(); //Estado Transient Produto p = new Produto(); p.setNome("Macarrão"); em.getTransaction().commit(); Graficamente, podemos representar esse estado da seguinte forma: Estado Managed (Gerenciado) O estado Managed é o estado onde o JPA reconhece a existência de um objeto-entidade e, consequentemente, o JPA garante que esse objeto terá representação idêntica no banco de dados. Isso significa que qualquer alteração que você fizer nesse objeto será automaticamente persistido no banco. Um detalhe importante: a fluxo de sincronização parte sempre do objeto para o banco de dados, nunca ao contrário. Isso significa que o JPA não detecta alterações realizadas diretamente no banco de dados. De acordo com a figura sobre o ciclo de vida das entidades (1ª figura), para que um objeto-
  • 2. entidade vá para o estado Managed, os métodos persist, merge, find ou getReference devem ser invocados para avisar aoEntityManager sobre a existência do objeto e para que este seja controlado por aquele. Abaixo temos um código que coloca a variável "p" sob gestão do EntityManager. EntityManager em = //Obtém o entity manager em.getTransaction().begin(); //Estado Transient Produto p = new Produto(); p.setNome("Macarrão"); //Estado Managed em.persist(p); //momento 1 p.setNome("Macarrão Integral"); //momento 2 em.getTransaction().commit(); //momento 3 No "momento 1" (execução do método persist), o JPA irá realizar um INSERT no banco de dados com o nome "Macarrão", irá recuperar o ID gerado pelo banco (por causa da anotação @GeneratedValue), irá atribuir esse valor à propriedade anotada com o @Id (propriedade "id") e irá colocar o objeto "p" sob gestão do EntityManager (o estado muda para Managed). No "momento 2" (apenas a execução de um set), houve uma alteração na propriedade nome. Como o objeto já está sendo gerenciado pelo EntityManager, o objeto é marcado como "sujo" para ser atualizado futuramente. Observe que não é necessário um novo persist (ou merge) porque o objeto já está sendo gerenciado pelo EntityManager. No "momento 3" ocorre o commit. O JPA dispara um UPDATE no banco de dados para manter uma representação idêntica no banco - o nome do produto passa a ser "Macarrão Integral". É importante ressaltar que a execução do persist dispara, imediatamente, um INSERT para o banco de dados (ocorre na hora). Por outro lado, por questões de economia, quando um objeto gerenciado sofre uma alteração em uma propriedade (um set), o UPDATE para o banco de dados é adiado até a execução de umcommit (o UPDATE não ocorre na hora). Graficamente, podemos representar o "momento 1", o "momento 2" e o "momento 3" da seguinte forma: Abaixo apresentamos um outro exemplo de código que obtém um Produto através do método find e atualiza o seu nome para "Macarrão de Ovos". Observe que, após a alteração do nome do produto, não é necessário fazer uma chamada merge para que os dados sejam persistidos porque o método find já coloca o objeto-entidade "p" em estado gerenciado. Novamente, o JPA irá garantir uma fiel representação desse objeto no banco e realiza um UPDATE automaticamente após o commit. EntityManager em = //Obtém o entity manager em.getTransaction().begin(); //Estado Managed Produto p = em.find(Produto.class, 1); p.setNome("Macarrão de Ovos"); em.getTransaction().commit(); A característica do estado Managed é que o objeto-entidade possui um ID, é conhecido pelo EntityManagere possui a informação no banco de dados.
  • 3. Estado Detached (Destacado) Imagine que você tenha uma funcionalidade com várias telas organizadas em abas (estilo Wizard) e que o usuário precisa acrescentar dados em todas elas até uma confirmação final. Imagine também que você tenha um objeto-entidade gerenciado que esteja sendo utilizado nessas abas. Durante a navegação, esse objeto-entidade sofre vários sets em seus atributos (e cada aba tem um commit) até a confirmação final (última aba). Como o objeto está gerenciado pelo EntityManager, cada tela concluída irá disparar um UPDATE no banco, aumentando a quantidade de round trips para o banco e prejudicando o desempenho do sistema. O objetivo do método detach é retirar, temporariamente, o objeto-entidade gerenciado para um estado não gerenciado para que problemas descritos no cenário acima não ocorram. A característica desse estado é que os objetos-gerenciados possuem um ID, provavelmente possui a informação no banco, mas não está sendo gerenciado pelo EntityManager. Se você também dar um new em um objeto-entidade e atribuir manualmente um ID a ele, ele também torna-se um objeto destacado. Abaixo temos um código que retira a variável "p" da gestão do EntityManager. EntityManager em = //Obtém o entity manager em.getTransaction().begin(); //Estado Managed Produto p = em.find(Produto.class, 1); //Estado Detached em.detach(p); p.setNome("Macarrão Instantâneo"); em.getTransaction().commit(); Graficamente, podemos representar o resultado do código acima da seguinte forma: Quando o usuário finalizar todo o processo clicando no botão salvar da última aba, desejamos sincronizar as diferenças de "p" com o banco de dados chamando o método merge. Aqui tem uma pegadinha que devemos tomar cuidado: ao executar esse método, o JPA faz um SELECT no banco, cria um outro objeto-entidade chamada "p1" com os valores encontrados no banco; coloca esse objeto em estado gerenciado (Managed); atribui as diferença de valores de "p" a "p1" e; como "p1" está gerenciado e houve alteração de propriedade, ele torna-se "sujo" para um UPDATE futuro (após um commit). Observe que "p" continua destacado e qualquer alteração que você realizar sobre ele não surtirá efeito no banco. Observe o código abaixo: EntityManager em = //Obtém o entity manager em.getTransaction().begin(); //Estado Managed Produto p = em.find(Produto.class, 1); //Estado Detached em.detach(p); p.setNome("Macarrão Instantâneo"); //Momento 1 e 2. em.merge(p); //Momento 3. p.setNome("Macarrão de Microondas");
  • 4. //Momento 4 em.getTransaction().commit(); Veja abaixo a explicação dos momentos 1, 2, 3 e 4: É um erro comum o programador achar que, após um merge, o objeto-entidade volta ao estado gerenciado. Como consequência, as informações inseridas no objeto-entidade após o merge serão perdidas, como ocorreu com a informação "Macarrão de Microondas". Para resolver esse problema, devemos atribuir a "p" o resultado o método merge, que retorna a instância "p1" gerenciada e recém criada. Segue o código correto: EntityManager em = //Obtém o entity manager em.getTransaction().begin(); //Estado Managed Produto p = em.find(Produto.class, 1); //Estado Detached em.detach(p); p.setNome("Macarrão Instantâneo"); //Dados sincronizados no banco. p = em.merge(p); //Agora "p" está gerenciado (Managed) e a alteração abaixo é salva no banco p.setNome("Macarrão de Microondas"); em.getTransaction().commit(); Há também os métodos clear e close que também colocam os objetos-entidades em estado Detached. A diferença entre eles é que o clear coloca todos os objetos-entidades gerenciados pelo EntityManager para o estado Detached sem matar o gerenciador (em outras palavras, podemos dizer que o clear "bota todo mundo pra fora" sem fechar a firma). O método close, além de "botar todo mundo pra fora", ele mata oEntityManager (a firma fecha). Estado Removed (Removido) O último estado, Removed, é quando queremos excluir um objeto-entidade do banco. A característica de um objeto removido é que ele possui um ID, não está mais gerenciado pelo EntityManager e não está mais no banco de dados. Observe na figura sobre o ciclo de vida das entidades (1ª figura) que o objeto-entidade só pode ser removido se estiver, primeiro, em um estado Gerenciado. Abaixo ocorre um erro se você tentar executar o seguinte código: EntityManager em = //Obtém o entity manager em.getTransaction().begin(); //Estado Transient Produto p = new Produto(); //Estado Detached p.setId(1); em.remove(p); //ERRO: "Detached" não passa para "Removed". em.getTransaction().commit();
  • 5. Por fim, o correto deveria ser: EntityManager em = //Obtém o entity manager em.getTransaction().begin(); //Estado Transient Produto p = new Produto(); //Estado Detached p.setId(1); em.remove(em.merge(p)); //OK: merge coloca "p" em estado "Managed". em.getTransaction().commit(); Concluímos nosso primeiro estudo sobre Persistência considerando a especificação JPA e esperamos que o assunto abordado facilite o seu dia-a-dia nesse complexo mundo Object- Relational Mapping (ORM).