Update em primary key com hibernate

Por acaso alguém sabe como faço pra fazer um update em uma chave primária com o hibernate?

flw

Não sei se entendi bem o que vc quer, mas, p/ atualizar um registro vc pode fazer +ou- isso :

                            Session s = HibernateFactory.getSession();

	Transaction tx = null;
	try {
		tx = s.beginTransaction();

		s.update( p ); //p objeto produto
		s.flush();

		tx.commit();

	} catch (RuntimeException e) {
		if (tx != null)
			tx.rollback();
		 //e.printStackTrace();
		throw new RuntimeException(e.getMessage());

	} finally {
		s.close();
	}

Não é isso.

Quero trocar o valor da chave.

Ex.:

Tabela
-------
campo1 pk
campo2 pk
campo3

Imagine o seguinte:
campo1 pk = 1
campo2 pk = 2
campo3 = "teste"

Agora quero alterar o valor do campo1 de 1 para 5

Esse é o problema.

O ID de um objeto é a identidade dele, quando se altera o id altera-se na verdade a identidade do objeto e isso implicaria na altualização ou não das dependencias bem como em um erro de constraint. Acho que o hibernate leva isso bem ao pé da letra, portanto se vc precisa disso jogue o objeto antigo fora (delete) e adicione um novo objeto com o novo Id.

Pode não ser a solução dos sonhos, mas se vc pensar bem vai ver que faz sentido.

:wink:

Concordo !!!

Imagine que vc pediu, quero o produto de codigo = 1

ele traz p/ vc

qdo vc muda o codigo de 1 p/ 5 ele vai procurar o registro na base e não vai encontrar , acho que vc teria que excluir e incluir de novo, fora as dependências com outras tabelas…

Mas se eu achar alguma coisa , dou um toque !!!

Já pensei e implementei isso :slight_smile: , mas, isso implica em excluir todas as dependencia, dessa forma fica complicado.

Queria uma forma de alterar a pk e as dependências em cascata.

flw,

Tentei fazer e olha a msg que dá

Unexpected row count: 0 expected: 1

está dando a mesma mensagem p/ vc ???

porque vc está precisando fazer isso ???

Sinceramente, me diz qual a real necessidade de atualizar um PK? Não consigo entender onde isso seja necessário… :roll:

Tem algum banco de dados que permite fazer isso? @.@

No SQLServer nas poucas vezes que fiz cagada e precisei alterar o ID, tive que alterar a tabela retirando a marcação de PK na coluna, alterar o valor e então marcar como PK de novo.

Oxe, isso por aqui é conhecido como gambiarra :lol:

Maurício Linhares. Gambiarra? Caro colega, deixo aberto para vc formular sua sugestão :wink:.

LIPE. Quanto ao banco de dados:
Estou utilizando o Postgresql e este suporta cascateamento de update ou delete para os relacionamentos. Sei que isso fere questões referentes a portabilidade, mas, antes limitar a gama de bancos do que limitar as funcionalidades do sistema :slight_smile: .

vmorikawa. Isso acontece porque vc tentou fazer um update com a id já alterada. Dessa forma como ele não encontrou nenhum registro para o update lançando essa exception.
Na session tem um metodo sobrecarregado do update que recebe o objeto + a chave, só que ele altera apenas os dados que não são chave.
O update poderia ser feito com hql, mas esse tem várias restrições não atendendo a necessidade.

volnei. Quanto ao caso de uso é o seguinte:

Não sei se alguém já trabalhou com estrutura de equipamentos, mas, vou tentar descrever brevemente:
Imagine que tenha a seguinte estrutura de objetos mapeados:

Estrutura
---------
EstruturaPK id
...
List itensSubstituicao

EstruturaPK
-----------
Produto produtoPai
Produto componente
Long item

Produto
-------
Long codigo
String descricao
...

ItemSubstituicao
----------------
Estrutura
Produto componenteSubstituivel
...

Isso é utilizado para se montar a estrutura de um produto fabricado. Dessa forma obtem-se vários valores como peso total da estrutura referente ao produto final e outros.
Agora o caso de uso:
Imagine que o componente utilizado na montagem da estrutura do produto não seja mais fabricado. O novo produto designado para substituir esse é cadastrado e as estruturas que contem o componente antigo devem ser atualizadas. Por coincidencia, e para correta modelagem e integridade do BD, este faz parte da é chave primária :smiley: .

Sugestões são bem vindas.

flw

Olha, eu acho bem mais fácil colocar o novo produto na base e fazer os outros produtos que dependem dele apontarem pra ele, do que fazer um cascateamento de chaves, especialmente usando Hibernate, onde trafegar e montar um grafo de objetos é tão complicado quanto chamar métodos get/set.

E eu disse que era gambiarra, porque pra mim parece gambiarra mesmo, não vejo nenhuma dificuldade de retirar a referência pra o objeto que não é mais produzido e colocar uma referência pro outro objeto lá.

Como você explicaria essas suas tabelas em objetos?

A questão é que não se tem produtos apontando para produtos e sim objetos que os relacionam e que no mundo relacional seguindo as regras de normalização ficam dispostos da forma que mostrei.
Reconheço a complexidade em mapear o mundo relacional para o OO e também que nosso companheiro :slight_smile: hibernate é o cara nesse quesito.
Quanto a montar novamente a estrutura com o novo produto, isso, impactaria em todas as dependencias, ficando inviável.

Também não via problema algum até esbarrar nesse caso. Tirar referência é fácil, o problema é o que isso vai gerar ao ser traduzido para o relacional.

[quote=fabriciogiordani]
Também não via problema algum até esbarrar nesse caso. Tirar referência é fácil, o problema é o que isso vai gerar ao ser traduzido para o relacional.[/quote]

Mas não é o Hibernate que vai fazer isso pra você? Ele provavelmente não vai se enganar :smiley:

Pois é, como falei acima e como o vmorikawa acabou testando, o hibernate monta o update baseado na id do objeto. Dessa forma se for fazer um update(objeto) com a chave alterada o hibernate vai tentar montar um update com where baseado nos valores da id do objeto do parâmetro, o que vai resultar em uma exception, pois, não vai encontrar nenhum registro para tal alteração.
Tentei então utilizar update(objeto, id), mas, esse mesmo que no objeto a id esteja alterada e passe a id antiga por parâmetro a qual ele teria que utilizar para montar o where para o update, ele monta o where, mas não inclui os campos chave no update.

Mas não foi esse o modo que eu disse, eu falei sobre atualizar os objetos que apontam pra esse objeto aí, não o contrário.

Pense em objeto, não em tabelas :smiley:

É bem mais fácil atualizar as referências.

E outra vez, como você modelou isso em objetos?