Cannot delete or update a parent row: a foreign key constraint fails

7 respostas
R

Isso ocorre quando tento deletar algo que está relacionado com outras tabelas.Como vocês tratam isso?

Vi que é causado por isso:
Caused by: java.sql.BatchUpdateException

Então tentei criar um bloco try/catch para se pegar isso mostrar uma mensagem dizendo ao usuario que não pode deletar isso porque está sendo usado em outro cadastro, só que o netbeans não deixa porque fala que essa exceção não é disparada no bloco…

Já passaram por algo semelhante? O que fizeram?

7 Respostas

D

Vc está usando JDBC puro?
Qual o código?

R

Estou usando Hibernate

O código?

try { //exclui o objeto curso e se der tudo certo comita e transacao session.delete(usuario); t.commit(); FacesUtils.mensInfo("Excluído com sucesso"); } catch (Exception e) { FacesUtils.mensInfo("Erro ao excluir!" + e.getMessage()); }

Quando tento excluir algo que esta vinculado com outra tabela, pega essa exception que falei acima.Só que se tento tratar ela, fala que ela não é disparada no bloco acima.

R

O pior é em outro formulário onde tenho um relacionamento 1:1, por exemplo:

Quando cadastro um usuário junto cadastra um complemento, são duas tabelas diferentes, porém estão ligadas e tem o mesmo id sempre(complemento id=1 pertence ao usuario id=1).
Então quando deleto um usuário logicamente vou deletar seu respectivo complemento, tentei fazer uma gambiarra aqui, mas não deu certo, porque pega essa exceção também...

Como faço isso?

Código:

public String excluir() throws Exception {
        //Cria a sessão com o banco e a transação
        Session session = HibernateUtil.getSession();
        Transaction t = session.beginTransaction();

        Usuario usuario = getUsuarioParaEditarExcluir();
        
        try{
            excluiComplemento(usuario);
            FacesUtils.mensInfo("Complemento excluído com sucesso");
        } catch(Exception e){
            FacesUtils.mensInfo("Erro ao excluir!" + e.getMessage());
        }
        
        try {
            //exclui o objeto usuario e se der tudo certo comita e transacao
            session.delete(usuario);
            t.commit();
            FacesUtils.mensInfo("Excluído com sucesso");
        } catch (Exception e) {
            FacesUtils.mensInfo("Erro ao excluir!" + e.getMessage());
        }

        //assim que removido
        //inicia um novo objeto
        this.novoUsuario();
        //n�o vai a lugar algum
        return null;
    }

    public void excluiComplemento(Irmao irmao) {
        //Cria a sessão com o banco e a transação
        Session session = HibernateUtil.getSession();
        Transaction t = session.beginTransaction();

        Query q = session.createQuery("from Complemento where id = " + usuario.getId());
        Complemento complemento = (Complemento) q.uniqueResult();
        
        session.delete(complemento);
        t.commit();
    }
D

Dá uma olhada como está sua lógica…
Vc abre duas transações, uma independente da outra, acho que é isso que esá lhe trazendo problemas.
Existe mesmo a necessidade de criar um método para excluir o complemento?

Quanto a excessão de excluir uma coisa que está amarrada em outra, tente verificar dentro do catch se a excessão lançada é do tipo java.sql.BatchUpdateException.

catch ( Exception exc ) { if ( exc instanceof java.sql.BatchUpdateException ) //trate aqui... }

Se bem que eu acho que essa excessão é um pouco abstrata demais. Acho que vc deveria tentar tratar excessões do tipo ConstraintViolationException.
O Hibernate tem uma série de excessões que retratam melhor o problema.

Essa excessão é lançada justamente porque por padrão o hibernate utiliza ON DELETE RESTRICT nas associações entre as tabelas.

[]´s

A

So pra complementar o hibernate pode fazer cascade delete caso vc queira isso, mas precisa ser habilitado na anotação/xml.

/peace

R

Ok Obrigado pela ajuda, vou dar uma pesquisada em relação a isso, qualquer problema eu retorno ;D

K

Já tive esse problema tb. Primeiro, verifique a sua configuração de cascade da relação que vc esta tentando deletar ou atualizar. Aqui uso a seguinte:

@ManyToOne(cascade={ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.REMOVE })

Outra coisa, se vc estiver fazendo um update, ou mesmo delete, tente usar o método merge do hibernate ao invés do update ou savaOrUpdate.

Criado 4 de novembro de 2008
Ultima resposta 6 de nov. de 2008
Respostas 7
Participantes 4