Entidades Managed, Transient e Detached no Hibernate e JPA

Entidades Managed, Transient e Detached no Hibernate e JPA
peas
peas

Compartilhe

Distinguir entre os estados de uma entidade no JPA/Hibernate é difícil no início. Um objeto é dito transiente quando não tem representação no banco de dados e nem o EntityManager o conhece, como abaixo:

 Cliente c = new Cliente(); 

Aqui, qualquer mudança no objeto referido por c não gerará nenhum tipo de insert ou update no banco de dados. O oposto é quando o objeto existe no banco de dados e o EntityManager em questão possui uma referência para ele, essa entidade está managed, gerenciada pelo EntityManager. Considere em uma referência a um EntityManager no seguinte exemplo:

 Cliente c = new Cliente(); // transiente em.persist(c); // gerenciado 

Ou ainda:

 Cliente c = em.find(Cliente.class, 1); // gerenciado 

Quando uma entidade está managed, qualquer mudança em seu estado (como uma chamada de setter) resultará em uma atualização no banco de dados no momento do commit.

O último caso é quando a entidade representa algo que possivelmente está no banco de dados, mas o EntityManager o desconhece: a entidade está fora do contexto, detached. Exemplo:

 Cliente c = new Cliente(); c.setId(1); 

Uma entidade também está detached quando o EntityManager de onde tiramos esse Cliente (por exemplo, quando fizemos um find ou vindo de uma Query) já não está mais aberta. Qualquer mudança nessa referência obviamente não surtirá efeito no banco de dados. Para que essa mudança faça efeito, isto é, para reattach o entidade, antes precisamos amarrá-la ao contexto de persistência. Repare que no EntityManager já pode existir uma entidade Cliente com esse mesmo id, imagine então o que aconteceria se tivéssemos um método que se chamasse reattach ou update?

Por isso o método é o merge. Ele junta a possível entidade com mesmo id que se encontra no EntityManager com a passada como argumento, e devolve a que está managed. O método merge não faz reattach. Então:

 Cliente c = new Cliente(); c.setId(1); em.merge(c); c.setNome("Cliente com nome alterado"); 

Não surtirá efeito! Aqui você precisava antes ter pego o que o merge devolveu. Repare na pequena alteração:

 Cliente c = new Cliente(); c.setId(1); c = em.merge(c); c.setNome("Cliente com nome alterado"); 

Pronto. Uma pequena introdução sobre o ciclo de vida de uma entidade em relação a um EntityManager: transient (a especificação chama de new), managed e detached! Ainda temos o estado removed, quando uma entidade está marcada para a remoção.

Veja outros artigos sobre Programação