Eu tenho essencialmente alguns objetos nesta configuração (o modelo de dados real é um pouco mais complexo):
- A tem um relacionamento muitos para muitos com B. (B tem
inverse="true"
) - B tem uma relação muitos-para-um com C. (eu
cascade
configurei para"save-update"
) - C é um tipo de tabela de tipo / categoria.
Além disso, provavelmente devo mencionar que as chaves primárias são geradas pelo banco de dados ao salvar.
Com meus dados, às vezes tenho problemas em que A tem um conjunto de objetos B diferentes e esses objetos B se referem ao mesmo objeto C.
Quando eu chamar session.saveOrUpdate(myAObject)
, eu recebo um erro de hibernação dizendo: "a different object with the same identifier value was already associated with the session: C"
. Eu sei que o Hibernate não pode inserir / atualizar / excluir o mesmo objeto duas vezes na mesma sessão, mas há alguma maneira de contornar isso? Esta não parece ser uma situação tão incomum.
Durante minha pesquisa desse problema, vi pessoas sugerirem o uso de session.merge()
, mas quando faço isso, quaisquer objetos "conflitantes" são inseridos no banco de dados como objetos em branco com todos os valores definidos como nulos. Obviamente, não é isso que queremos.
[Editar] Outra coisa que esqueci de mencionar é que (por razões arquitetônicas além do meu controle), cada leitura ou gravação precisa ser feita em uma sessão separada.
Respostas:
Muito provavelmente é porque os objetos B não estão se referindo à mesma instância do objeto Java C. Eles estão se referindo à mesma linha no banco de dados (ou seja, a mesma chave primária), mas são cópias diferentes dela.
Então o que está acontecendo é que a sessão do Hibernate, que está gerenciando as entidades, estaria monitorando qual objeto Java corresponde à linha com a mesma chave primária.
Uma opção seria certificar-se de que as entidades de objetos B que se referem à mesma linha estão realmente se referindo à mesma instância de objeto de C. Como alternativa, desative o cascateamento para essa variável de membro. Dessa forma, quando B é persistente, C não é. Você terá que salvar C manualmente separadamente. Se C for uma tabela de tipo / categoria, provavelmente faz sentido ser assim.
fonte
Apenas defina cascade como MERGE, isso deve funcionar.
fonte
Você só precisa fazer uma coisa. Corre
session_object.clear()
e salve o novo objeto. Isso limpará a sessão (como apropriadamente nomeado) e removerá o objeto duplicado ofensivo de sua sessão.fonte
Eu concordo com @Hemant Kumar, muito obrigado. De acordo com sua solução, resolvi meu problema.
Por exemplo:
Person.java
Este código sempre erra na minha aplicação :,
A different object with the same identifier value was already associated with the session
depois descobri que esqueci de aumentar automaticamente a minha chave primária!Minha solução é adicionar este código à sua chave primária:
fonte
Isso significa que você está tentando salvar várias linhas em sua tabela com referência ao mesmo objeto.
verifique a propriedade id da sua classe de entidade.
para
fonte
Transfira a tarefa de atribuição do ID do objeto do Hibernate para o banco de dados usando:
Isso resolveu o problema para mim.
fonte
Adicione a anotação @GeneratedValue ao bean que você está inserindo.
fonte
Uma maneira de resolver o problema acima será substituir o
hashcode()
.Também limpe a sessão de hibernação antes e depois de salvar.
Definir explicitamente o objeto destacado como
null
também ajuda.fonte
Acabei de encontrar esta mensagem, mas em código c #. Não tenho certeza se é relevante (exatamente a mesma mensagem de erro).
Eu estava depurando o código com pontos de interrupção e expandindo algumas coleções por meio de membros privados enquanto o depurador estava em um ponto de interrupção. Ter executado novamente o código sem vasculhar as estruturas fez a mensagem de erro desaparecer. Parece que o ato de examinar as coleções privadas carregadas lentamente fez o NHibernate carregar coisas que não deveriam ser carregadas naquele momento (porque estavam em membros privados).
O próprio código está envolvido em uma transação bastante complicada que pode atualizar um grande número de registros e muitas dependências como parte dessa transação (processo de importação).
Esperançosamente, uma pista para qualquer pessoa que se deparar com o problema.
fonte
Encontre o atributo "Cascade" no Hibernate e apague-o. Ao definir "Cascata" disponível, ele chamará outras operações (salvar, atualizar e excluir) em outras entidades que tenham relação com as classes relacionadas. Assim, o mesmo valor de identidades acontecerá. Funcionou comigo.
fonte
Tive esse erro alguns dias depois e gastei muito tempo para corrigi-lo.
Antes de receber esse erro, não mencionei o tipo de geração de ID no objeto OrderDetil. quando sem gerar o id de Orderdetails, ele mantém o Id como 0 para todos os objetos OrderDetail. foi isso que #jbx explicou. Sim, é a melhor resposta. este um exemplo de como isso acontece.
fonte
Tente colocar o código da sua consulta antes. Isso resolve meu problema. por exemplo, mude isso:
para isso:
fonte
você pode não definir o identificador do objeto antes de chamar a consulta de atualização.
fonte
Eu encontrei o problema porque a geração da chave primária está errada, quando insiro uma linha como esta:
Eu mudo a classe do gerador de id para identidade
fonte
No meu caso, apenas flush () não funcionou. Tive que usar um clear () após flush ().
fonte
se você usar EntityRepository, use saveAndFlush em vez de salvar
fonte
Se deixei uma aba de expressões em meu IDE aberta que estava fazendo uma chamada get de hibernação no objeto que está causando esta exceção. Eu estava tentando excluir este mesmo objeto. Também tive um ponto de interrupção na chamada de exclusão que parece ser necessário para que esse erro aconteça. Simplesmente fazer outra guia de expressões ser a guia frontal ou alterar a configuração para que o ide não pare nos pontos de interrupção resolveu este problema.
fonte
Certifique-se de que sua entidade tem o mesmo tipo de geração com todas as entidades mapeadas
Ex: UserRole
}
Módulo:
}
Entidade Principal com Mapeamento
}
fonte
Além de todas as respostas anteriores, uma possível correção para este problema em um projeto de grande escala, se você usar um objeto de valor para suas classes não definir o atributo id na classe VO Transformer.
fonte
apenas confirme a transação atual.
agora você pode começar outra transação e fazer qualquer coisa na entidade
fonte