O EntityManager.merge()
pode inserir novos objetos e atualizar os existentes.
Por que alguém iria querer utilizar persist()
(que só pode criar novos objetos)?
De qualquer forma, adicionará uma entidade a um PersistenceContext, a diferença está no que você faz com a entidade depois.
Persist toma uma instância de entidade, adiciona-a ao contexto e faz com que essa instância seja gerenciada (ou seja, futuras atualizações da entidade serão rastreadas).
A fusão cria uma nova instância da sua entidade, copia o estado da entidade fornecida e faz com que a nova cópia seja gerida. A instância que você passar não será gerenciada (quaisquer alterações que você fizer não farão parte da transação - a menos que você chame o Merge novamente).
Talvez um exemplo de código ajude.
MyEntity e = new MyEntity();
// scenario 1
// tran starts
em.persist(e);
e.setSomeField(someValue);
// tran ends, and the row for someField is updated in the database
// scenario 2
// tran starts
e = new MyEntity();
em.merge(e);
e.setSomeField(anotherValue);
// tran ends but the row for someField is not updated in the database
// (you made the changes *after* merging)
// scenario 3
// tran starts
e = new MyEntity();
MyEntity e2 = em.merge(e);
e2.setSomeField(anotherValue);
// tran ends and the row for someField is updated
// (the changes were made to e2, not e)
Os Cenários 1 e 3 são mais ou menos equivalentes, mas há algumas situações em que você gostaria de usar o Cenário 2.
Eu notei que quando eu usei o em.merge', eu recebi uma declaração
SELECT' para cada INSERT', mesmo quando não havia nenhum campo que o JPA estava gerando para mim - o campo chave primário era um UUID que eu mesmo defini. Eu mudei para
em.persist(myEntityObject)e recebi apenas declarações
INSERT` então.
Eu estava recebendo exceções preguiçosas na minha entidade porque eu estava tentando acessar uma coleção preguiçosa carregada que estava em sessão.
O que eu faria era em um pedido separado, recuperar a entidade da sessão e depois tentar acessar uma coleção na minha página jsp, o que era problemático.
Para aliviar isso, atualizei a mesma entidade no meu controlador e a passei para o meu jsp, embora eu imagine que quando salvei novamente em sessão, ela também estará acessível através de 'SessionScope' e não atirei uma 'LazyLoadingException', uma modificação do exemplo 2:
O seguinte funcionou para mim:
// scenario 2 MY WAY
// tran starts
e = new MyEntity();
e = em.merge(e); // re-assign to the same entity "e"
//access e from jsp and it will work dandy!!