Quando Hibernate libera uma sessão, como se decidir quais objetos na sessão estão sujos?

StackOverflow https://stackoverflow.com/questions/82429

Pergunta

O meu entendimento de Hibernate é que, como os objetos são carregados a partir do DB eles são adicionados à sessão. Em vários pontos, dependendo da sua configuração, a sessão é liberado. Neste ponto, objetos modificados são gravados no banco de dados.

Como o Hibernate decidir quais objetos são 'sujo' e necessidade de ser escrito?

Será que os proxies gerados por trabalhos de interceptação Hibernate aos campos, e adicionar o objeto para uma lista suja na Sessão?

Ou faz olhar Hibernate em cada objeto na Sessão e compará-lo com os objetos estado original?

Ou algo completamente diferente?

Foi útil?

Solução

Hibernate faz / pode usar geração de bytecode (CGLIB) para que ele saiba um campo está sujo assim que você chamar o setter (ou mesmo atribuir ao AFAICT campo).

Isto imediatamente marcas que campo / objeto como sujo, mas não reduz o número de objetos que precisam ser verificados durante o flush-sujo. Tudo que faz é afetar a implementação de org.hibernate.engine.EntityEntry.requiresDirtyCheck(). É ainda faz uma comparação campo a campo para verificar se há sujeira.

Eu digo que o acima com base em uma rede de arrasto recente através do código fonte (3.2.6GA), com qualquer credibilidade que acrescenta. Os pontos de interesse são:

  • SessionImpl.flush() dispara um evento onFlush().
  • SessionImpl.list() chama autoFlushIfRequired() que desencadeia um evento onAutoFlush(). (Nas mesas de interesse). Ou seja, as consultas podem invocar um flush. Curiosamente, sem flush ocorre se não houver nenhuma transação.
  • Ambos esses eventos eventualmente acabar em AbstractFlushingEventListener.flushEverythingToExecutions(), o que acaba (entre outros locais interessantes) na flushEntities().
  • Que laços mais de cada entidade na sessão (source.getPersistenceContext().getEntityEntries()) chamando DefaultFlushEntityEventListener.onFlushEntity().
  • Você eventualmente acabar em dirtyCheck(). Esse método faz algumas otimizações wrt para bandeiras sujas CGLIB, mas ainda acabei looping sobre cada entidade.

Outras dicas

Hibernate tira um instantâneo do estado de cada objeto que é carregado na sessão. Na descarga, cada objecto na sessão é comparado com o seu correspondente instantâneo para determinar quais os que estão sujos. instruções SQL são emitidos conforme necessário, e os instantâneos são atualizados para refletir o estado da (agora limpa) Session objetos.

Dê uma olhada para org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck Cada elemento na sessão vai para esse método para determinar se ele está sujo ou não, comparando com uma versão intocada (um a partir do cache ou um a partir do banco de dados).

Hibernate padrão mecanismo de checagem suja irá percorrer entidades ligadas atuais e combinar todas as propriedades contra os seus valores iniciais em tempo de carregamento.

Você pode visualizar melhor este processo no diagrama a seguir:

Default checagem suja automática

Estas respostas são incompletas (na melhor das hipóteses - Eu não sou um perito aqui). Se você tem uma entidade homem hib em sua sessão, você não faz nada para ele, você ainda pode obter uma atualização emitida quando você chamar save () sobre ele. quando? quando outro atualizações de sessão que objeto entre o load () e save (). aqui é o meu exemplo disso: hibernate sets a bandeira suja (e problemas de atualização), mesmo que o cliente não alterar o valor

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top