Qual é a diferença entre persist () e merge () no Hibernate?

Qual é a diferença entre persist () e merge () no Hibernate?

persist() pode criar uma consulta UPDATE & INSERT, por exemplo:

 SessionFactory sef = cfg.buildSessionFactory(); Session session = sef.openSession(); A a=new A(); session.persist(a); a.setName("Mario"); session.flush(); 

Neste caso, a consulta será gerada assim:

 Hibernate: insert into A (NAME, ID) values (?, ?) Hibernate: update A set NAME=? where ID=? 

Portanto, o método persist() pode gerar uma Inserção e uma Atualização.

Agora com merge() :

 SessionFactory sef = cfg.buildSessionFactory(); Session session = sef.openSession(); Singer singer = new Singer(); singer.setName("Luciano Pavarotti"); session.merge(singer); session.flush(); 

Isso é o que eu vejo no database:

 SINGER_ID SINGER_NAME 1 Ricky Martin 2 Madonna 3 Elvis Presley 4 Luciano Pavarotti 

Agora atualize um registro usando merge()

 SessionFactory sef = cfg.buildSessionFactory(); Session session = sef.openSession(); Singer singer = new Singer(); singer.setId(2); singer.setName("Luciano Pavarotti"); session.merge(singer); session.flush(); 

Isso é o que eu vejo no database:

 SINGER_ID SINGER_NAME 1 Ricky Martin 2 Luciano Pavarotti 3 Elvis Presley 

A especificação JPA contém uma descrição muito precisa da semântica dessas operações, melhor do que no javadoc:

A semântica da operação persist , aplicada a uma entidade X, é a seguinte:

  • Se X for uma nova entidade, ela será gerenciada. A entidade X será inserida no database em ou antes da confirmação de transação ou como resultado da operação de liberação.

  • Se X for uma entidade gerenciada preexistente, ela será ignorada pela operação persistente. No entanto, a operação de persistência é em cascata para entidades referenciadas por X, se os relacionamentos de X para essas outras entidades forem anotados com o valor do elemento de anotação cascade=PERSIST ou cascade=ALL ou especificados com o elemento descritor XML equivalente.

  • Se X for uma entidade removida, ela será gerenciada.

  • Se X for um object desanexado, a EntityExistsException poderá ser lançada quando a operação persist for chamada, ou a EntityExistsException ou outra PersistenceException poderá ser lançada no flush ou no tempo de confirmação.

  • Para todas as entidades Y referenciadas por um relacionamento de X, se o relacionamento com Y tiver sido anotado com o valor do elemento em cascade=PERSIST ou cascade=ALL , a operação persist será aplicada a Y.


A semântica da operação de mesclagem aplicada a uma entidade X é a seguinte:

  • Se X for uma entidade desanexada, o estado de X será copiado para uma instância de entidade gerenciada preexistente X ‘da mesma identidade ou uma nova cópia gerenciada X’ de X será criada.

  • Se X for uma nova instância de entidade, uma nova instância de entidade gerenciada X ‘será criada e o estado de X será copiado para a nova instância de entidade gerenciada X’.

  • Se X for uma instância de entidade removida, uma IllegalArgumentException será lançada pela operação de mesclagem (ou a confirmação da transação falhará).

  • Se X for uma entidade gerenciada, ela será ignorada pela operação de mesclagem, no entanto, a operação de mesclagem será transmitida em cascata para entidades referenciadas por relacionamentos de X se esses relacionamentos tiverem sido anotados com o valor do elemento em cascade=MERGE ou em cascade=ALL .

  • Para todas as entidades Y referenciadas por relacionamentos de X com o valor do elemento cascade=MERGE ou cascade=ALL , Y é mesclado recursivamente como Y ‘. Para todos esses Y referenciados por X, X ‘é configurado para referenciar Y’. (Note que se X é gerenciado, então X é o mesmo object que X ‘.)

  • Se X é uma entidade mesclada a X ‘, com uma referência a outra entidade Y, onde cascade=MERGE ou cascade=ALL não é especificada, então a navegação da mesma associação de X’ produz uma referência a um object gerenciado Y ‘com o mesma identidade persistente de Y.

Isso vem da JPA. De uma maneira muito simples:

persist (entidade) deve ser usado com entidades totalmente novas, para adicioná-las ao database (se a entidade já existir no database, haverá lançamento EntityExistsException).

merge (entidade) deve ser usado, para colocar a entidade de volta ao contexto de persistência se a entidade foi separada e alterada.

Persist deve ser chamado apenas em novas entidades, enquanto a mesclagem destina-se a reconectar entidades desanexadas.

Se você estiver usando o gerador atribuído, usar a mesclagem em vez de persistir pode causar uma instrução SQL redundante , afetando, portanto, o desempenho.

Além disso, chamar a mesclagem para entidades gerenciadas também é um erro, pois as entidades gerenciadas são gerenciadas automaticamente pelo Hibernate e seu estado é sincronizado com o registro do database pelo mecanismo de verificação suja ao liberar o Contexto de persistência .