Qual é a utilidade de session.flush () no Hibernate

110

Quando estamos atualizando um registro, podemos usar session.flush()com o Hibernate. Qual é a necessidade flush()?

CHANTI
fonte

Respostas:

138

O esvaziamento da sessão força o Hibernate a sincronizar o estado na memória do Sessioncom o banco de dados (ou seja, para gravar alterações no banco de dados). Por padrão, o Hibernate irá liberar as alterações automaticamente para você:

  • antes de algumas execuções de consulta
  • quando uma transação é confirmada

Permitir limpar explicitamente o Sessionfornece um controle mais preciso que pode ser necessário em algumas circunstâncias (para obter um ID atribuído, para controlar o tamanho da Sessão, ...).

Pascal Thivent
fonte
8
Observe que esta resposta descreve o comportamento DEFAULT Hibernate: o comportamento de liberação pode ser alterado por meio da configuração Modo de liberação. Os detalhes estão em docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/… (versão 3.5).
SteveT
1
Encontrei o documento onde está dito exatamente o que você está dizendo, mas tenho dúvidas de que qual será a prioridade significa suponha 1) Eu tenho uma classe onde estou salvando o objeto usando o código id = session.save(obj);e a transação é confirmada na próxima linha, mas o obj não está sendo salvo para DB, por quê? 2) Salvei obj usando session.save(obj);com commit e ao retornar usei return obj.getprimaryID();Neste caso, obj é salvo no DB. Então, por que esse comportamento está acontecendo?
Amogh
74

Como corretamente dito nas respostas acima, ao chamar flush(), forçamos o hibernate a executar os comandos SQL no banco de dados. Mas entenda que as mudanças ainda não foram "confirmadas". Então, depois de fazer o flush e antes de fazer o commit, se você acessar o banco de dados diretamente (digamos do prompt do SQL) e verificar as linhas modificadas, NÃO verá as mudanças.

Isso é o mesmo que abrir 2 sessões de comando SQL. E as alterações feitas em 1 sessão não são visíveis para os outros até que sejam confirmadas.

Kaushik Lele
fonte
12
Bem - as mudanças podem ser ligeiramente visíveis. Por exemplo, uma linha não confirmada pode criar um bloqueio na linha inserida mas não confirmada e atrasar a mesma linha de ser inserida por outra sessão até que a transação seja confirmada ou revertida. Portanto, não é totalmente invisível.
rghome
2
Naveguei por toda a web e esta é a resposta que finalmente me fez entender. Obrigado.
Siddhartha
qual é a utilidade de colocar .flush () em um loop for então se commit () faz um flush no final?
Eildosa
@Kaushik Lele Qual é o ponto de flush () se os dados não são visíveis após flush? Você pode explicar alguns dos casos de uso mais refinados em que isso é útil?
java_geek
28

Só sei que quando chamamos session.flush()nossas instruções são executadas no banco de dados, mas não confirmadas.

Suponha que não chamemos o flush()método no objeto de sessão e se chamarmos o método commit, ele fará internamente o trabalho de executar instruções no banco de dados e, em seguida, confirmar.

commit=flush+commit (em caso de funcionalidade)

Portanto, concluo que, quando chamamos o método flush () no objeto Session, ele não obtém o commit, mas atinge o banco de dados e executa a consulta e também obtém o rollback.

Para confirmar, usamos commit () no objeto Transaction.

Shoaib Chikate
fonte
Você pode dar alguns detalhes sobre a necessidade de enxágue?
java_geek
14

Liberar a sessão faz com que os dados que estão atualmente na sessão sejam sincronizados com os que estão no banco de dados.

Mais no site do Hibernate:

flush()é útil, porque não há absolutamente nenhuma garantia sobre quando a Sessão executa as chamadas JDBC, apenas a ordem em que são executadas - exceto você usa flush().

Miku
fonte
Você pode fornecer um cenário em que o usuário deve se preocupar com a sequência? O uso de hibernar é para tornar as coisas relacionadas ao banco de dados transparentes para o usuário. Quando fazemos "commit", a liberação ocorre automaticamente. Qual é o cenário em que você fará o flush, mas não fará o commit?
Kaushik Lele
1
@KaushikLele você pode consultar esta questão stackoverflow.com/questions/37382872/…
GMsoF
10

Você pode usar flushpara forçar as restrições de validação a serem realizadas e detectadas em um local conhecido, em vez de quando a transação for confirmada. Pode ser quecommit seja chamado implicitamente por alguma lógica de estrutura, por meio de lógica declarativa, o contêiner ou por um modelo. Nesse caso, qualquer exceção lançada pode ser difícil de capturar e manipular (pode ser muito alta no código).

Por exemplo, se você save()um novo objeto EmailAddress, que tem uma restrição exclusiva no endereço, não receberá um erro até que faça o commit.

Chamar flush()força a inserção da linha, lançando uma exceção se houver uma duplicata.

No entanto, você terá que reverter a sessão após a exceção.

rghome
fonte
4

Eu gostaria apenas de combinar todas as respostas fornecidas acima e também relacionar o método Flush () com Session.save () para dar mais importância

Hibernate save () pode ser usado para salvar a entidade no banco de dados. Podemos invocar esse método fora de uma transação, por isso não gosto desse método para salvar dados. Se usarmos isso sem transação e tivermos cascateamento entre entidades, apenas a entidade primária será salva, a menos que liberemos a sessão.

flush (): Força o esvaziamento da sessão. É usado para sincronizar os dados da sessão com o banco de dados.

Quando você chama session.flush (), as instruções são executadas no banco de dados, mas não são confirmadas. Se você não chamar session.flush () e se você chamar session.commit (), internamente o método commit () executa a instrução e confirma.

Portanto, commit () = flush + commit. Portanto, session.flush () apenas executa as instruções no banco de dados (mas não confirma) e as instruções NÃO ESTÃO mais NA MEMÓRIA. Ele apenas força o esvaziamento da sessão.

Alguns pontos importantes:

Devemos evitar salvar fora do limite da transação, caso contrário, as entidades mapeadas não serão salvas, causando inconsistência de dados. É muito normal esquecer a liberação da sessão porque isso não lança nenhuma exceção ou aviso. Por padrão, o Hibernate irá liberar as alterações automaticamente para você: antes de algumas execuções de consulta quando uma transação é confirmada. Permitir limpar explicitamente a Sessão oferece um controle mais preciso que pode ser necessário em algumas circunstâncias (para obter um ID atribuído, para controlar o tamanho da Sessão )

Sundar Gsv
fonte
3

O flush() método faz com que o Hibernate libere a sessão. Você pode configurar o Hibernate para usar o modo de liberação para a sessão usando o setFlushMode()método. Para obter o modo de liberação para a sessão atual, você pode usar o getFlushMode()método. Para verificar se a sessão está suja, você pode usarisDirty() método. Por padrão, o Hibernate gerencia a liberação das sessões.

Conforme indicado na documentação:

https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/flushing/Flushing.html

Rubor

Flushing é o processo de sincronizar o estado do contexto de persistência com o banco de dados subjacente. O EntityManagere o HibernarSession expõem um conjunto de métodos, através dos quais o desenvolvedor da aplicação pode alterar o estado persistente de uma entidade.

O contexto de persistência atua como um cache write-behind transacional, enfileirando qualquer mudança de estado de entidade. Como qualquer cache write-behind, as alterações são primeiro aplicadas na memória e sincronizadas com o banco de dados durante o tempo de liberação. A operação de liberação pega cada mudança de estado de entidade e a traduz em um INSERT, UPDATEouDELETE declaração.

A estratégia de liberação é fornecida pelo flushMode da Sessão do Hibernate em execução no momento. Embora JPA defina apenas duas estratégias de liberação ( AUTOe COMMIT), o Hibernate tem um espectro muito mais amplo de tipos de liberação :

  • ALWAYS: Libera a sessão antes de cada consulta;
  • AUTO: Este é o modo padrão e ele libera a Sessão apenas se necessário;
  • COMMIT: A Sessão tenta atrasar a liberação até que a Transação atual seja confirmada, embora também possa ser liberada prematuramente;
  • MANUAL: A liberação de sessão é delegada ao aplicativo, que deve ser chamado Session.flush()explicitamente para aplicar as alterações de contexto de persistência.

Por padrão, o Hibernate usa o AUTOmodo de descarga que dispara uma descarga nas seguintes circunstâncias:

  • antes de comprometer uma Transação;
  • antes de executar uma consulta JPQL / HQL que se sobrepõe às ações da entidade enfileirada;
  • antes de executar qualquer consulta SQL nativa que não tenha sincronização registrada.

fonte
1

Ligar EntityManager#flushtem efeitos colaterais . Ele é convenientemente usado para tipos de entidade com valores de ID gerados (valores de sequência): tal ID está disponível apenas na sincronização com a camada de persistência subjacente. Se esse ID for necessário antes que a transação atual termine (para fins de registro, por exemplo), é necessário liberar a sessão.

johanwannheden
fonte
0

Com este método, você evoca o processo de limpeza. Este processo sincroniza o estado do seu banco de dados com o estado da sua sessão, detectando mudanças de estado e executando as respectivas instruções SQL.

lennoxGER
fonte