Aqui está o meu entendimento dos métodos. Principalmente, eles são baseados na API, já que eu não uso todos eles na prática.
saveOrUpdate As
chamadas são salvas ou atualizadas dependendo de algumas verificações. Por exemplo, se não houver identificador, save será chamado. Caso contrário, a atualização é chamada.
salvar
Persiste uma entidade. Atribuirá um identificador se não existir. Se alguém faz, está essencialmente fazendo uma atualização. Retorna o ID gerado da entidade.
update
Tenta persistir a entidade usando um identificador existente. Se nenhum identificador existir, acredito que uma exceção seja lançada.
saveOrUpdateCopy
Isso foi descontinuado e não deve mais ser usado. Em vez disso, há ...
fundir
Agora, este é o lugar onde meu conhecimento começa a vacilar. O importante aqui é a diferença entre entidades transitórias, desanexadas e persistentes. Para mais informações sobre os estados do objeto, dê uma olhada aqui . Com salvar e atualizar, você está lidando com objetos persistentes. Eles estão vinculados a uma sessão para que o Hibernate saiba o que mudou. Mas quando você tem um objeto transitório, não há sessão envolvida. Nesses casos, você precisa usar a mesclagem para atualizações e persistir para salvar.
persistir
Como mencionado acima, isso é usado em objetos transitórios. Ele não retorna o ID gerado.
fonte
update
um objeto transitório é bom, não recebi uma exceção.Consulte o Fórum do Hibernate para obter uma explicação das diferenças sutis entre persistir e salvar. Parece que a diferença é o momento em que a instrução INSERT é finalmente executada. Como o save retorna o identificador, a instrução INSERT deve ser executada instantaneamente, independentemente do estado da transação (que geralmente é uma coisa ruim). Persist não executará nenhuma instrução fora da transação atualmente em execução apenas para atribuir o identificador. Salvar / Persistir funcionam em instâncias transitórias , ou seja, instâncias que ainda não possuem um identificador atribuído e, como tal, não são salvas no banco de dados.
Atualizar e mesclar funcionam em instâncias desanexadas , ou seja, instâncias que possuem uma entrada correspondente no banco de dados, mas que atualmente não estão anexadas a (ou gerenciadas por) uma Sessão. A diferença entre eles é o que acontece com a instância que é passada para a função. update tenta anexar novamente a instância, o que significa que não deve haver nenhuma outra instância da entidade persistente conectada à sessão no momento, caso contrário, uma exceção será lançada. mesclar , no entanto, apenas copia todos os valores para uma instância persistente na sessão (que será carregada se não estiver carregada no momento). O objeto de entrada não é alterado. Então mesclar é mais geral que atualizar, mas pode usar mais recursos.
fonte
save() - If an INSERT has to be executed to get the identifier, then this INSERT happens immediately, no matter if you are inside or outside of a transaction. This is problematic in a long-running conversation with an extended Session/persistence context.
Você pode me dizer como uma inserção pode ocorrer fora de uma sessão e por que é ruim?INSERT
ed. Consequentemente, nesses casos, você não pode retornar um identificador agora sem que ele seja gerado. Para gerá-lo, você deve executarINSERT
agora . Como uma transação de longa execução não é executada no momento, mas apenas no commit, a única maneira de executar oINSERT
now é executá-la fora do TX.Este link explica de maneira adequada:
http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/
Todos nós temos os problemas que encontramos com pouca frequência que, quando os vemos novamente, sabemos que resolvemos isso, mas não conseguimos lembrar como.
A NonUniqueObjectException lançada ao usar Session.saveOrUpdate () no Hibernate é uma das minhas. Vou adicionar novas funcionalidades a um aplicativo complexo. Todos os meus testes de unidade funcionam bem. Então, ao testar a interface do usuário, tentando salvar um objeto, começo a receber uma exceção com a mensagem "um objeto diferente com o mesmo valor de identificador já estava associado à sessão". Aqui está um exemplo de código do Java Persistence with Hibernate.
Para entender a causa dessa exceção, é importante entender os objetos desanexados e o que acontece quando você chama saveOrUpdate () (ou apenas atualiza ()) em um objeto desanexado.
Quando fechamos uma sessão individual do Hibernate, os objetos persistentes com os quais trabalhamos são desanexados. Isso significa que os dados ainda estão na memória do aplicativo, mas o Hibernate não é mais responsável pelo rastreamento de alterações nos objetos.
Se modificarmos nosso objeto desanexado e quisermos atualizá-lo, teremos que anexar novamente o objeto. Durante esse processo de recolocação, o Hibernate verificará se há outras cópias do mesmo objeto. Se encontrar alguma, precisa nos dizer que não sabe mais o que é a cópia “real”. Talvez outras alterações tenham sido feitas nas outras cópias que esperamos que sejam salvas, mas o Hibernate não as conhece, porque não as estava gerenciando na época.
Em vez de salvar possíveis dados incorretos, o Hibernate nos fala sobre o problema via NonUniqueObjectException.
Então, o que devemos fazer? No Hibernate 3, temos merge () (no Hibernate 2, use saveOrUpdateCopy ()). Este método forçará o Hibernate a copiar quaisquer alterações de outras instâncias desanexadas para a instância que você deseja salvar e, assim, mescla todas as alterações na memória antes da gravação.
É importante observar que a mesclagem retorna uma referência à versão recém-atualizada da instância. Não está anexando novamente o item à sessão. Se você testar por exemplo a igualdade (item == item3), verá que ele retornará false nesse caso. Você provavelmente desejará trabalhar com o item3 deste ponto em diante.
Também é importante observar que a JPA (Java Persistence API) não tem um conceito de objetos desanexados e reconectados e usa EntityManager.persist () e EntityManager.merge ().
Descobri em geral que, ao usar o Hibernate, saveOrUpdate () geralmente é suficiente para minhas necessidades. Normalmente, só preciso usar a mesclagem quando tenho objetos que podem ter referências a objetos do mesmo tipo. Mais recentemente, a causa da exceção estava no código validando que a referência não era recursiva. Eu estava carregando o mesmo objeto na minha sessão como parte da validação, causando o erro.
Onde você encontrou esse problema? A mesclagem funcionou para você ou você precisava de outra solução? Você prefere sempre usar a mesclagem ou prefere usá-lo apenas conforme necessário para casos específicos
fonte
Na verdade, a diferença entre hibernação
save()
epersist()
métodos depende da classe de gerador que estamos usando.Se nossa classe gerador é atribuído, então não há nenhuma diferença entre
save()
epersist(
métodos). Como o gerador 'atribuído' significa, como programador, precisamos fornecer o valor da chave primária para salvar no banco de dados corretamente [Espero que você conheça esse conceito de geradores] No caso de uma classe geradora diferente da atribuída, suponha que se o nome da nossa classe de gerador for Incrementar O hibernate ele próprio atribuirá o valor do ID da chave primária no banco de dados à direita [exceto o gerador atribuído, o hibernate usado apenas para cuidar do valor do ID da chave primária, lembre-se], portanto, neste caso, se chamarmossave()
oupersist()
método, ele inserirá o registro em o banco de dados normalmente Mas, ouça, osave()
método pode retornar o valor do ID da chave primária que é gerado pelo hibernate e podemos vê-lo porNesse mesmo caso,
persist()
nunca devolverá nenhum valor ao cliente.fonte
Encontrei um bom exemplo mostrando as diferenças entre todos os métodos de salvamento do hibernate:
http://www.journaldev.com/3481/hibernate-session-merge-vs-update-save-saveorupdate-persist-example
Em resumo, de acordo com o link acima:
Salve ()
persistir()
saveOrUpdate ()
Pode ser usado com ou sem a transação e, assim como save (), se usado sem a transação, as entidades mapeadas não serão salvas;
Resultados em consultas de inserção ou atualização com base nos dados fornecidos. Se os dados estiverem presentes no banco de dados, a consulta de atualização será executada.
atualizar()
mesclar ()
Também para exemplos práticos de todos estes, consulte o link que mencionei acima, mostra exemplos para todos esses métodos diferentes.
fonte
Como expliquei neste artigo , você deve preferir os métodos JPA na maioria das vezes, e os
update
tarefas de processamento em lote.Uma entidade JPA ou Hibernate pode estar em um dos quatro estados a seguir:
A transição de um estado para outro é feita pelos métodos EntityManager ou Session.
Por exemplo, a JPA
EntityManager
fornece os seguintes métodos de transição de estado da entidade.O Hibernate
Session
implementa todos osEntityManager
métodos JPA e fornece alguns métodos adicionais de transição de estado de entidadesave
, como ,saveOrUpdate
eupdate
.Persistir
Para alterar o estado de uma entidade de Transitório (Novo) para Gerenciado (Persistido), podemos usar o
persist
método oferecido pela JPA,EntityManager
que também é herdado pelo HibernateSession
.Portanto, ao executar o seguinte caso de teste:
O Hibernate gera as seguintes instruções SQL:
Observe que o
id
é atribuído antes de anexar aBook
entidade ao contexto de persistência atual. Isso é necessário porque as entidades gerenciadas são armazenadas em umaMap
estrutura em que a chave é formada pelo tipo de entidade e seu identificador e o valor é a referência da entidade. Esta é a razão pela qual o JPAEntityManager
e o HibernateSession
são conhecidos como cache de primeiro nível.Ao chamar
persist
, a entidade é anexada apenas ao Contexto de Persistência em execução no momento, e o INSERT pode ser adiado até que oflush
seja chamado.A única exceção é o gerador IDENTITY que aciona o INSERT imediatamente, pois é a única maneira de obter o identificador da entidade. Por esse motivo, o Hibernate não pode inserir em lotes para entidades usando o gerador de IDENTITY. Para mais detalhes sobre este tópico, consulte este artigo .
Salve
O
save
método específico do Hibernate é anterior à JPA e está disponível desde o início do projeto Hibernate.Para ver como o
save
método funciona, considere o seguinte caso de teste:Ao executar o caso de teste acima, o Hibernate gera as seguintes instruções SQL:
Como você pode ver, o resultado é idêntico à
persist
chamada do método. No entanto, diferentementepersist
, osave
método retorna o identificador da entidade.Para mais detalhes, consulte este artigo .
Atualizar
O
update
método específico do Hibernate tem como objetivo ignorar o mecanismo de verificação suja e forçar uma atualização de entidade no momento da liberação.Para ver como o
update
método funciona, considere o exemplo a seguir, que persiste umaBook
entidade em uma transação, modifica-a enquanto a entidade está no estado desanexado e força o SQL UPDATE usando aupdate
chamada de método.Ao executar o caso de teste acima, o Hibernate gera as seguintes instruções SQL:
Observe que ele
UPDATE
é executado durante a liberação do contexto de persistência, logo antes da confirmação, e é por isso que aUpdating the Book entity
mensagem é registrada primeiro.Usando
@SelectBeforeUpdate
para evitar atualizações desnecessáriasAgora, o UPDATE sempre será executado, mesmo que a entidade não tenha sido alterada enquanto estiver no estado desanexado. Para evitar isso, você pode usar a
@SelectBeforeUpdate
anotação Hibernate, que acionará umaSELECT
instrução que buscouloaded state
que é usada pelo mecanismo de verificação suja.Portanto, se anotamos a
Book
entidade com a@SelectBeforeUpdate
anotação:E execute o seguinte caso de teste:
O Hibernate executa as seguintes instruções SQL:
Observe que, desta vez, não há
UPDATE
execução, pois o mecanismo de verificação suja do Hibernate detectou que a entidade não foi modificada.SaveOrUpdate
O
saveOrUpdate
método específico do Hibernate é apenas um alias parasave
eupdate
.Agora, você pode usar
saveOrUpdate
quando quiser persistir em uma entidade ou forçar umUPDATE
conforme ilustrado pelo exemplo a seguir.Cuidado com o
NonUniqueObjectException
Um problema que pode ocorrer com
save
,update
esaveOrUpdate
é se o contexto de persistência já contém uma referência de entidade com o mesmo ID e do mesmo tipo como no exemplo a seguir:Agora, ao executar o caso de teste acima, o Hibernate lançará um
NonUniqueObjectException
porque o segundoEntityManager
já contém umaBook
entidade com o mesmo identificador que passamosupdate
, e o Contexto de Persistência não pode conter duas representações da mesma entidade.Mesclar
Para evitar isso
NonUniqueObjectException
, você precisa usar omerge
método oferecido pela JPAEntityManager
e herdado pelo HibernateSession
também.Conforme explicado neste artigo , ele
merge
busca um novo instantâneo de entidade do banco de dados se não houver uma referência de entidade encontrada no Contexto de Persistência e copia o estado da entidade desanexada passada para omerge
método.Para ver como o
merge
método funciona, considere o exemplo a seguir, que persiste em umBook
entidade em uma transação, modificando-o enquanto a entidade está no estado desanexado e passando a entidade desanexada paramerge
um Contexto de Persistência subsequente.Ao executar o caso de teste acima, o Hibernate executou as seguintes instruções SQL:
Observe que a referência da entidade retornada por
merge
é diferente da referência desanexada que passamos para omerge
método.Agora, embora você deva preferir usar o JPA
merge
ao copiar o estado da entidade desconectada, o extraSELECT
pode ser problemático ao executar uma tarefa de processamento em lote.Por esse motivo, você deve preferir usá-
update
lo quando tiver certeza de que não há referência de entidade já anexada ao Contexto de Persistência atualmente em execução e que a entidade desanexada foi modificada.Para mais detalhes sobre este tópico, consulte este artigo .
Conclusão
Para persistir em uma entidade, você deve usar o
persist
método JPA . Para copiar o estado da entidade desanexada,merge
deve ser preferido. Oupdate
método é útil apenas para tarefas de processamento em lote. Osave
esaveOrUpdate
são apenas aliases paraupdate
e você provavelmente não deve usá-los.Alguns desenvolvedores chamam
save
mesmo quando a entidade já está gerenciada, mas isso é um erro e aciona um evento redundante, pois, para entidades gerenciadas, o UPDATE é tratado automaticamente no tempo de liberação do contexto de Persistência.Para mais detalhes, consulte este artigo .
fonte
Esteja ciente de que se você chamar uma atualização em um objeto desanexado, sempre haverá uma atualização no banco de dados, independentemente de você ter alterado ou não o objeto. Se não é o que você deseja, use Session.lock () com LockMode.None.
Você deve chamar update somente se o objeto tiver sido alterado fora do escopo da sua sessão atual (quando estiver no modo desanexado).
fonte
Nenhuma das respostas a seguir está correta. Todos esses métodos parecem iguais, mas na prática fazem coisas absolutamente diferentes. É difícil fazer comentários curtos. Melhor fornecer um link para a documentação completa sobre esses métodos: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/objectstate.html
fonte
Nenhuma das respostas acima está completa. Embora a resposta de Leo Theobald pareça a resposta mais próxima.
O ponto básico é como o hibernate está lidando com estados de entidades e como ele lida com eles quando há uma alteração de estado. Tudo deve ser visto com relação a liberações e confirmações, que todos parecem ter ignorado completamente.
NUNCA UTILIZE O MÉTODO DE POUPANÇA DE HIBERNATE. ESQUEÇA QUE MESMO EXISTE EM HIBERNADO!
Persistir
Como todos explicaram, o Persist basicamente transita uma entidade do estado "Transitório" para o estado "Gerenciado". Nesse ponto, uma lama ou uma confirmação pode criar uma instrução de inserção. Mas a entidade ainda permanece no estado "Gerenciado". Isso não muda com o flush.
Nesse ponto, se você "persistir" novamente, não haverá alterações. E não haverá mais salvamentos se tentarmos manter uma entidade persistente.
A diversão começa quando tentamos despejar a entidade.
Um despejo é uma função especial do Hibernate que fará a transição da entidade de "Gerenciado" para "Desanexado". Não podemos chamar uma persistência em uma entidade desanexada. Se fizermos isso, o Hibernate gera uma exceção e a transação inteira é revertida no commit.
Mesclar vs Atualização
Estas são 2 funções interessantes que fazem coisas diferentes quando tratadas de maneiras diferentes. Ambos estão tentando fazer a transição da entidade do estado "Desanexado" para o estado "Gerenciado". Mas fazendo diferente.
Entenda o fato de que Desanexado significa um tipo de estado "offline". e gerenciado significa o estado "Online".
Observe o código abaixo:
Quando você faz isso? O que você acha que acontecerá? Se você disse que isso gerará uma exceção, está correto. Isso gerará uma exceção porque, a mesclagem funcionou no objeto de entidade, que é o estado desanexado. Mas isso não altera o estado do objeto.
Nos bastidores, a mesclagem gera uma consulta de seleção e basicamente retorna uma cópia da entidade que está no estado anexado. Observe o código abaixo:
O exemplo acima funciona porque a mesclagem trouxe uma nova entidade para o contexto que está no estado persistente.
Quando aplicado com o Update, o mesmo funciona bem porque o update não traz uma cópia da entidade como mesclagem.
Ao mesmo tempo, no rastreamento de depuração, podemos ver que o Update não levantou a consulta SQL de seleção como mesclagem.
excluir
No exemplo acima, usei delete sem falar sobre delete. A exclusão basicamente fará a transição da entidade do estado gerenciado para o estado "removido". E quando liberado ou confirmado, emitirá um comando de exclusão para armazenar.
No entanto, é possível trazer a entidade de volta ao estado "gerenciado" do estado "removido" usando o método persist.
Espero que a explicação acima tenha esclarecido qualquer dúvida.
fonte