Eu recebo o seguinte erro de hibernação. Consigo identificar a função que causa o problema. Infelizmente, existem várias chamadas de banco de dados na função. Não consigo encontrar a linha que causa o problema, pois o hibernate liberou a sessão no final da transação. O erro de hibernação abaixo mencionado parece um erro geral. Nem sequer mencionou qual Bean causa o problema. Alguém familiarizado com esse erro de hibernação?
org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1
at org.hibernate.jdbc.BatchingBatcher.checkRowCount(BatchingBatcher.java:93)
at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:79)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:985)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:333)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransacti
onManager.java:500)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManag
er.java:473)
at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(Transaction
AspectSupport.java:267)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
Respostas:
Sem códigos e mapeamentos para suas transações, será quase impossível investigar o problema.
No entanto, para entender melhor o que causa o problema, tente o seguinte:
Espero que ajude.
fonte
Recebi a mesma exceção ao excluir um registro por ID que não existe. Portanto, verifique se o registro que você está atualizando / excluindo realmente existe no banco de dados
fonte
Solução: no arquivo de mapeamento Hibernate para a propriedade id, se você usar qualquer classe geradora, para essa propriedade, não deverá definir o valor explicitamente usando um método setter.
Se você definir explicitamente o valor da propriedade Id, isso levará o erro acima. Marque isso para evitar esse erro. ou É erro mostrar quando você menciona no arquivo de mapeamento o campo generator = "native" ou "incremental" e no seu DATABASE a tabela mapeada não é auto_incremented Solução: Vá para o seu DATABASE e atualize sua tabela para definir auto_increment
fonte
Isso aconteceu comigo acidentalmente quando eu estava atribuindo IDs específicos a alguns objetos (teste) e depois estava tentando salvá-los no banco de dados. O problema era que no banco de dados havia uma política específica para configurar os IDs dos objetos. Apenas não atribua um ID se você tiver uma política no nível do Hibernate.
fonte
No meu caso, cheguei a essa exceção em dois casos semelhantes:
@Transactional
eu recebi uma chamada para outro serviço (com longos tempos de resposta). O método atualiza algumas propriedades da entidade (após o método, a entidade ainda existe no banco de dados). Se o usuário solicitar duas vezes o método (como ele acha que não funciona na primeira vez) ao sair do método transacional pela segunda vez, o Hibernate tenta atualizar uma entidade que já mudou seu estado desde o início da transação. Quando o Hibernate procura uma entidade em um estado e encontra a mesma entidade, mas já foi alterada pela primeira solicitação, lança uma exceção, pois não pode atualizar a entidade. É como um conflito no GIT.Conclusão: no meu caso, não foi um problema que pode ser encontrado no código. Essa exceção é lançada quando o Hibernate descobre que a entidade buscada pela primeira vez no banco de dados foi alterada durante a transação atual , portanto, não pode liberá-la no banco de dados, pois o Hibernate não sabe qual é a versão correta da entidade: a atual busca de transação no início; ou o que já está armazenado no banco de dados.
Solução: para resolver o problema, você precisará jogar com o Hibernate LockMode para encontrar o que melhor se adapta às suas necessidades.
fonte
LockMode.READ
ou nãoLockMode.OPTIMISTIC
.Acabei de encontrar esse problema e descobri que estava excluindo um registro e tentando atualizá-lo posteriormente em uma transação do Hibernate.
fonte
Isso pode acontecer quando os acionadores executam consultas DML adicionais (modificação de dados) que afetam a contagem de linhas. Minha solução foi adicionar o seguinte na parte superior do meu gatilho:
fonte
Eu estava enfrentando o mesmo problema. O código estava funcionando no ambiente de teste. Mas não estava funcionando no ambiente de preparação.
O problema era que a tabela tinha entrada única para cada chave primária no teste da tabela do banco de dados. Mas no banco de dados de teste, havia várias entradas para a mesma chave primária. (O problema está no preparo do banco de dados. A tabela não tinha restrições de chave primária e também havia várias entradas.)
Portanto, sempre que ocorre uma operação de atualização, falha. Ele tenta atualizar o registro único e espera obter a contagem de atualizações como 1. Mas, como havia 3 registros na tabela para a mesma chave primária, a contagem de atualizações de resultados encontra 3. A contagem esperada de atualizações e a contagem real de atualizações de resultados não coincidem. , Lança exceção e reverte.
Após a remoção de todos os registros que possuem chave primária duplicada e adicionamos restrições de chave primária. Está funcionando bem.
contagem real de linhas: 0 // significa que nenhum registro foi encontrado para atualizar a
atualização: 0 // significa que nenhum registro foi encontrado, portanto, não há atualização
esperada: 1 // significa que se espera pelo menos 1 registro com a chave na tabela db.
Aqui o problema é que a consulta tentando atualizar um registro para alguma chave, mas o hibernate não encontrou nenhum registro com a chave.
fonte
Como Julius diz, isso acontece quando uma atualização ocorre em um objeto que tem seus filhos excluídos. (Provavelmente porque havia a necessidade de uma atualização para todo o Objeto Pai, e às vezes preferimos excluir os filhos e reinseri-los no Pai (novos e antigos não importam) junto com outras atualizações que o pai poderia ter em qualquer um dos seus outros campos simples) Então ... para que isso funcione, exclua os filhos (dentro de uma Transação) chamando
childrenList.clear()
(Não faça um loop entre os filhos e exclua cada um com algunschildDAO.delete(childrenList.get(i).delete()))
e definindo@OneToMany(cascade = CascadeType.XXX ,orphanRemoval=true)
no lado do objeto pai. Atualize o pai (fatherDAO.update (father)). (Repita para cada objeto pai) O resultado é que as crianças têm seu vínculo com o pai removido e, em seguida, elas são removidas como órfãs pela estrutura.fonte
Encontrei esse problema em que tínhamos um relacionamento com muitos.
No arquivo de mapeamento hbernate hbm para mestre, para objeto com arranjo de tipo de conjunto, adicionado
cascade="save-update"
e funcionou bem.Sem isso, por padrão, o hibernate tenta atualizar para um registro inexistente e, ao fazer isso, ele é inserido.
fonte
Isso também pode acontecer quando você tenta
UPDATE
uma CHAVE PRIMÁRIA .fonte
Eu tenho o mesmo problema e verifiquei que isso pode ocorrer devido à chave primária de incremento automático. Para resolver esse problema, não insira o valor de incremento automático com o conjunto de dados. Inserir dados sem a chave primária.
fonte
Outra maneira de obter esse erro é se você tiver um item nulo em uma coleção.
fonte
isso acontece quando você tenta excluir o mesmo objeto e, em seguida, atualiza novamente o mesmo objeto, use isso após excluir
session.clear ();
fonte
Isso aconteceu comigo também, porque eu tinha meu ID como Long e estava recebendo da visualização o valor 0 e, quando tentei salvar no banco de dados, recebi esse erro, então o corrigi definindo o ID como nulo.
fonte
Corri para esse problema quando estava iniciando e confirmando manualmente transações dentro do método anotado como
@Transactional
. Corrigi o problema detectando se uma transação ativa já existia.Depois, permiti que o Spring se encarregasse de confirmar a transação.
fonte
Isso acontece quando você declara o JSF Managed Bean como
quando você deve declarar como
Saudações;
fonte
Eu recebi esse erro quando tentei atualizar um objeto com um ID que não existia no banco de dados. O motivo do meu erro foi que eu havia atribuído manualmente uma propriedade com o nome 'id' à representação JSON do lado do cliente do objeto e, ao desserializar o objeto no lado do servidor, essa propriedade 'id' substituía a variável de instância ( também chamado de 'id') que o Hibernate deveria gerar. Portanto, tenha cuidado ao nomear colisões se estiver usando o Hibernate para gerar identificadores.
fonte
Eu também me deparei com o mesmo desafio. No meu caso, eu estava atualizando um objeto que nem existia, usando
hibernateTemplate
.Na verdade, no meu aplicativo, eu estava recebendo um objeto de banco de dados para atualizar. E enquanto atualizava seus valores, também atualizei seu ID por engano e fui em frente para atualizá-lo e me deparei com o referido erro.
Estou usando
hibernateTemplate
para operações CRUD.fonte
Depois de ler todas as respostas, não encontrou ninguém para falar sobre o atributo inverso do hibernate.
Na minha opinião, você também deve verificar no mapeamento de seus relacionamentos se a palavra-chave inversa está definida adequadamente. Inverso palavra-chave é criada para definir qual lado é o proprietário para manter o relacionamento. O procedimento para atualizar e inserir varia de acordo com este atributo.
Vamos supor que temos duas tabelas:
tabela principal , tabela intermediária
com um relacionamento de um para muitos . As classes de mapeamento do hiberntate são Principal e Middle, respectivamente.
Portanto, a classe Principal possui um conjunto de objetos do meio . O arquivo de mapeamento xml deve ser o seguinte:
Como inverso é definido como "true", significa que a classe "Middle" é o proprietário do relacionamento, portanto a classe Principal NÃO ATUALIZA o relacionamento.
Portanto, o procedimento para atualização pode ser implementado assim:
Isso funcionou para mim, mas você pode sugerir algumas edições para melhorar a solução. Dessa forma, todos nós estaremos aprendendo.
fonte
No nosso caso, finalmente descobrimos a causa raiz do StaleStateException.
Na verdade, estávamos excluindo a linha duas vezes em uma única sessão de hibernação. Anteriormente, estávamos usando o ojdbc6 lib, e isso estava ok nesta versão.
Mas quando atualizamos para odjc7 ou ojdbc8, a exclusão de registros duas vezes estava lançando uma exceção. Houve um erro no nosso código, onde estávamos excluindo duas vezes, mas isso não era evidente no ojdbc6.
Conseguimos reproduzir com este pedaço de código:
No primeiro flush, o hibernate vai e faz alterações no banco de dados. Durante o segundo flush, o hibernate compara o objeto da sessão com o registro da tabela real, mas não conseguiu encontrar um, daí a exceção.
fonte
Esse problema ocorre principalmente quando estamos tentando salvar ou atualizar o objeto que já foi buscado na memória por uma sessão em execução. Se você buscou um objeto da sessão e está tentando atualizar no banco de dados, essa exceção pode ser lançada.
Eu usei session.evict (); Para remover primeiro o cache armazenado na hibernação ou se você não quiser correr o risco de perder dados, é melhor criar outro objeto para armazenar a temperatura dos dados.
fonte
Problema no Hibernate 5.4.1 e HHH-12878
Antes do Hibernate 5.4.1, as exceções otimistas de falha de bloqueio (por exemplo,
StaleStateException
ouOptimisticLockException
) não incluíam a declaração de falha.O problema HHH-12878 foi criado para melhorar o Hibernate, para que, ao lançar uma exceção de bloqueio otimista, a
PreparedStatement
implementação do JDBC também seja registrada:Tempo de teste
Primeiro, definiremos uma
Post
entidade que define uma@Version
propriedade, permitindo, portanto, o mecanismo de bloqueio otimista implícito :Ativaremos o lote JDBC usando as três propriedades de configuração a seguir:
Vamos criar 3
Post
entidades:E o Hibernate executará uma inserção em lote JDBC:
Portanto, sabemos que o lote JDBC funciona perfeitamente.
Agora, vamos replicar o problema de bloqueio otimista:
A primeira transação seleciona todas as
Post
entidades e modifica otitle
propriedades.No entanto, antes que a primeira
EntityManager
seja liberada, executaremos uma segunda transição usando oexecuteSync
métodoA segunda transação modifica a primeira
Post
, entãoversion
será incrementada:Agora, quando a primeira transação tentar liberar o arquivo
EntityManager
, obteremos o seguinteOptimisticLockException
:Portanto, você precisa atualizar para o Hibernate 5.4.1 ou mais recente para se beneficiar dessa melhoria.
fonte
Isso aconteceu se você alterar algo no conjunto de dados usando a consulta sql nativa, mas o objeto persistente para o mesmo conjunto de dados estiver presente no cache da sessão. Use session.evict (yourObject);
fonte
O Hibernate armazena em cache objetos da sessão. Se o objeto for acessado e modificado por mais de 1 usuário,
org.hibernate.StaleStateException
poderá ser lançado. Pode ser resolvido com o método de entidade de mesclagem / atualização antes de salvar ou usar o bloqueio. Mais informações: http://java-fp.blogspot.lt/2011/09/orghibernatestalestateexception-batch.htmlfonte
Um dos casos
fonte
Eu estava enfrentando essa exceção e o hibernate estava funcionando bem. Tentei inserir manualmente um registro usando o pgAdmin, aqui o problema ficou claro. A consulta de inserção SQL retorna 0 inserção. e há uma função de gatilho que causa esse problema porque retorna nulo. então eu só tenho que configurá-lo para retornar novo. e finalmente resolvi o problema.
Espero que ajude qualquer corpo.
fonte
Eu recebi esse erro porque mapeei a
ID
coluna por engano usandoId(x => x.Id, "id").GeneratedBy.**Assigned**();
Problema resolvido usando
Id(x => x.Id, "id").GeneratedBy.**Identity**();
fonte
Isso acontece comigo porque falta a declaração de ID na classe de bean.
fonte
No meu caso, houve um problema com o banco de dados, pois um dos procs armazenados consumia toda a CPU, causando altos tempos de resposta do banco de dados. Depois que esse problema foi resolvido, foi resolvido.
fonte