Hibernate - 1:N - Cascade [ +- RESOLVIDO ]

16 respostas
F

Tenho certeza que este assunto já foi discutido bastante aqui, mas de tudo que tentei até agora nao obtive resultado.

Possuo um objeto Chamado, que tem uma lista de Pecas para a qual utilizo uma tabela associativa, ChamadoPeca, onde tenho o ID_CHAMADO, ID_PECA, VALOR_PECA, QTD_PECA.
Os processos de inserção e atualização estão funcionando corretamente, porém quando eu removo um ChamadoPeca este não é excluído do banco.
Segue os mapeamentos relacionados:

CHAMADO

<set name="pecas" cascade="all, delete-orphan" lazy="false" table="chamado_peca" fetch="join" inverse="true"> <key> <column name="Chamado" not-null="true" /> </key> <one-to-many class="tns.business.Entity.Chamado.ChamadoPeca" /> </set>

CHAMADO PECA

<many-to-one name="chamado" column="Chamado" not-null="true" class="tns.business.Entity.Chamado.Chamado" cascade="none" />

Desconfio que possa ser a forma como eu removo o item da lista, será ?

Obrigado desde já.

16 Respostas

V

Cara,

Faz um tempo que não uso Hibernate, mas se o seu mapeamento é 1 * N o mapeamento em Peça é desnecessário.

Vê isso ai, mas to meio enferrujado… rs

Q

feltraco, vc está tentando deletar o ChamadoPeca diretamente ou vc remove de uma lista obtida de um objeto Chamado?
outra coisa, gera algum log ou exceção?

sinceramente fiquei confuso com sua combinação de operações em cascata, ñ sei se é válida, mas acho q com mais informações e umpouco mais de leitura de documentação agente chega em uma solução

vitorfarias:
Cara,

Faz um tempo que não uso Hibernate, mas se o seu mapeamento é 1 * N o mapeamento em Peça é desnecessário.

Vê isso ai, mas to meio enferrujado… rs


é desnecessário se o relacionamento for unidirecional, para relacionamentos bidirecionais é preciso fazer o mapeamento nas duas entidades

flw, t+

F

@Vitor
Já tentei UNI e BI Direcional, por isso o mapemento está ali, como o @quikkoo disse.

@quikkoo
Já tentei das duas formas, mas pelo certo deveria funcionar somente removendo o objeto da lista, quando faço isso não me retorna nenhuma Exception somente não exclui o registro.
Se eu tento excluir manualmente me dá um erro de BatchUpdateException.

O que te deixou confuso quando as operações em cascada.

Grato pelas respostas

Q

esse BatchUpdateException deve aparecer com alguma mensagem, essa mensagem pode ajudar a achar o erro
mas eu li a documentação aqui pra poder me situar melhor sobre as cascatas, e me parece td certo com seu mapeamento, acho q vc deve conferir se o objeto ChamadoPeca q vc quer deletar ñ está vinculado a nenhum chamado, por causa do “delete-orphan”

verifica isso, e mostra a mensagem da exceção, flw, t+

F

@quikkoo
Recebo esta msg de BatchUpdateException quando fiz o mapeamento diferente, many-to-many com o coolum como unique, vi na doc.
Ai dava BatchUpdateException dizendo que o ID_CHAMADO nao podia ser null, tipo ele tentava atualizar em vez de deletar o objeto que nao existia mais.
Se deixo o mapeamento como esta nao gera excessao.

Tentei fazer isso, logo apos salvar o Chamado mas ainda dentro da msm transacao:

@SuppressWarnings("unchecked")
	private void removePecasLista(Chamado chamado)		
	{
		if (chamado.getPecas().size() > 0)
		{
			StringBuffer hql = new StringBuffer("from ChamadoPeca as p where p.chamado.id=");
			hql.append(chamado.getId());
			hql.append(" and p.id not in(");

			for (Iterator<ChamadoPeca> i = chamado.getPecas().iterator(); i.hasNext(); )
			{
				ChamadoPeca item = i.next();
				hql.append(item.getId());
				if (i.hasNext())
					hql.append(",");
			}
			hql.append(")");
			
			System.out.println("#######################################################################################");
			System.out.println("HQL: "+ hql.toString());
			System.out.println("#######################################################################################");
			
			List<ChamadoPeca> listaItensRemover = (List<ChamadoPeca>) this.templateHqlQuery(hql.toString());
			for (ChamadoPeca item:listaItensRemover)
				chamadoPecaDao.remove(item);
		}
	}

Neste caso recebo a seguinte msg de erro:

deleted object would be re-saved by cascade (remove deleted object from associations)
F

Alguem tem mais alguma dica, ou não funciona mesmo ?

Att

Q

eu precisaria testar na prática pra ter certeza, mas pela mensagem de erro me parece q o hibernate existe q vc remova as associações dos objetos antes de persisti-las na base de dados, ou seja, pra vc remover um peca, vc precisa antes remove-lo de todos os chamados (me refiro a objetos e nao a tabelas)

tente algo ± assim:

void deletaPeca(ChamadoPeca peca)
{
	Chamado chamado = peca.getChamado();
	chamado.getPecas().remove(peca);
	peca.setChamado(null);

	new ChamadoDao().update(chamado);
	new ChamadoPecaDao().remove(peca);
}

talvez essa ultima operação com o dao seja desnecessária, como eu disse, no momento nao tenho como testar se a lógica está correta, mas eu já passei por situações assim antes e foi mais ou menos assim que eu resolvi

flw, t+

F

@quikkoo
Entao cara, eu nao tenho esse ChamadoPeca pra ser removido.
Ele ja foi excluido do objeto pela interface.

Quando mando salvar novamente se antes tinha 3 ChamadoPeca, agora tem somente 1, po r exemplo.
Esses outros dois simplesmente foram removidos da lista.

Att

Q

uai, mas no código que vc postou, no último ‘for’, vc itera sobre uma lista de ChamadoPeca, e remove todos os elementos da banse de dados pelo objeto dao, o trecho de codigo q eu postei seria colocado justamente ali

vc só precisa mudar a forma como vc está removendo os objetos, se for preciso refaça algumas outras partes do código, mas acho q isso ñ seria necessário

flw. t+

F

No codigo q poste eu fazia um pouco diferente.
Eu excluia da base todos os ChamadoPeca, exceto os que estao na lista atual.
Faco uma consulta e depois excluo, exatamente por nao ter eles em memoria.

[]'s

F

Uma coisa que nao consigo entender, me corrijam se eu estiver errado.

Faço isoo:

e depois quando eu tento salvar o cahamado:

O Hibernate mesmo assim tenta salvar novamente o Item.
E ainda me dá a mensagem:

Entendo que ele deveria ou ignorar este Item ou tentar Remover ele e não tentar salvar novamente.

F

Estou desanimado com esse problema já.
estou quase decidindo fazer os controles das listas puramente com SQL

F

Mais um detalhe.

Levando em consideração que eu tinha 2 Pecas na lista dentro de Chamado, eu removo uma e mando persistir.

POr mais que eu declare:

Ele executa:

Hibernate: update tns.chamado
Hibernate: update tns.chamado_peca

Esta correto os updates mas ele nao remove o item que nao esta mais presente na lista.

Entao o “delete-orphan” não funciona ?

F

Acabei de atualizar o Hibernate para 3.5.5 Final.
Continua o mesmo problema.

F

[ ± RESOLVIDO]

Mudei os cascades para no chamado save-update e none no ChamadoPeca e Peca.

Ai quando mando persistir o Chamado, percorro a lista removendo 1 por 1 os itens que foram excluidos na interface.

Com Delete-orphan não consegui fazer funcionar.

Grato pela atenção.

F

Passei o dia todo sofrendo nesse cascade e resolvi da seguinte forma:

meu Bean ta assim:

@ManyToMany(fetch = FetchType.LAZY, cascade=CascadeType.ALL)
	@JoinTable(name = "ta_aluno_ocorrencia",
	joinColumns = { @JoinColumn(name = "id_aluno") },
	inverseJoinColumns = { @JoinColumn(name = "id_historico") })
	public List&lt;AlunoHistoricoOcorrencia&gt; getOcorrencias() {
		return ocorrencias;
	}

	@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
	public void setOcorrencias(List&lt;AlunoHistoricoOcorrencia&gt; ocorrencias) {
		this.ocorrencias = ocorrencias;
	}

E na hora de remover fiz o seguinte:

//carrego pelo id
                Aluno aluno = dao.carrega(aluno.getId());
		AlunoHistoricoOcorrencia ocorrencia = daoOcorrencia.carrega(id);
                //retiro da list
		aluno.getOcorrencias().remove(ocorrencia);
                //atualizo a list
		aluno.setOcorrencias(aluno.getOcorrencias());
                //removo do banco
		daoOcorrencia.exclui(ocorrencia);
                //atualizo o aluno
		dao.atualiza(aluno);

Espero que ajude ;)…

Criado 6 de setembro de 2010
Ultima resposta 7 de jul. de 2011
Respostas 16
Participantes 4