Exclusão de registro com associação utilizando hibernate

11 respostas
alepenchel

Olá pessoal.

SITUAÇÂO:
Estou excluindo uma entidade(PK), que se relaciona com outras entidades(FK).
Atualmente, quando isto ocorre, o hibernate lança ConstraintViolationException que eu trato e mando exibir uma mensagem genérica para o usuário informando que não é possível excluir pq existem registros associados.

Para o usuário esse cenário não é o ideal, já que ele gostariam que o sistema exibisse uma msg informando todas as associações.

A forma genérica que encontrei foi utilizando DatabaseMetaData do jdbc a partir da connection.

Alguém tem alguma solução mais elegante para isso, preferencialmente utilizando apenas a api do hibernate?

Obrigado.

11 Respostas

Hebert_Coelho

Com algo generico do hibernate não sei te falar.

O que você poderia fazer era:
List dependencias = casa.getDependencias();
dependencias seria o cara a exibir as dependências.

E o método casa.getDepencias (além de ser transiente) teria algo parecido com:

public List<String> getDependencias(){ List<String> dependencias = new ArrayList<String>(); if(casa.getCarro() != null ){ dependencias.add("carro"); } return dependencias; }

alepenchel

Obrigado pela resposta jakefrog.

Mas é exatamente isso que eu não quero fazer, pois tem muitas entidades com muitas associações.
Por isso preciso de algo genérico.

W

vc poderia mostrar o codigo de como vc vez para da a sua msg ? queria algo igual o seu

W

comigo, ele nao excluir do banco, e nao da erro pelo contrario ele diz que foi excluido, mais continua no banco

alguem poderia me ajudar ? BEAN
public String excluir(){
       UnidadeDAO pd = new UnidadeDAO();
         FacesContext msg = FacesContext.getCurrentInstance();
       try{
         pd.excluir(unidade);
        // SessionUtil.addSuccessMessage("OperacaoSucesso");
           msg.addMessage(null,
                  new FacesMessage(FacesMessage.SEVERITY_INFO,
                    "Excluido com sucesso.", null) );
            unidade = new Unidade();
        }catch (Exception e){
            //SessionUtil.addSuccessMessage("OperacaoFracasso");
              msg.addMessage(null,
                  new FacesMessage(FacesMessage.SEVERITY_WARN,
                    "Erro ao excluir.", null) );
        }
     return null ;
    }
DAO:
public void excluir(Unidade u){
        Session s = HibernateUtil.getSession();
        Transaction t = s.beginTransaction();
        try {
            s.delete(u);
            t.commit();
        } catch (Exception e) {
            t.rollback();
        }finally{
            s.close();
        }
    }
Hebert_Coelho

Pq daria erro? Você debugou seu código? Tenho certeza que você irá ver que ele vai cair no erro.

Dá uma olhada no seu código catch…

W

jakefrog:
Pq daria erro? Você debugou seu código? Tenho certeza que você irá ver que ele vai cair no erro.

Dá uma olhada no seu código catch…

na realidade, eu queria que ele mostrasse uma msg dizendo que nao poderia excluir pq tem associação, so que ele mostra “Excluido com sucesso.” mas nao exclui

Hebert_Coelho

WAO:
jakefrog:
Pq daria erro? Você debugou seu código? Tenho certeza que você irá ver que ele vai cair no erro.

Dá uma olhada no seu código catch…

na realidade, eu queria que ele mostrasse uma msg dizendo que nao poderia excluir pq tem associação, so que ele mostra “Excluido com sucesso.” mas nao exclui

Como você sabe que esse é seu erro se não aparece mensagem de erro algum?

ErickRAR

WAO, você tem que reavaliar como trata os erros. Se no DAO já tem o try/catch, você está tratando o erro nele, então o catch do metodo Excluir nunca irá pegar alguma exceção do DAO.
Para ajudar, use o método printStrackTrace nos catch’s para saber qual é o erro e onde estão acontecendo.

W

jakefrog:
WAO:
jakefrog:
Pq daria erro? Você debugou seu código? Tenho certeza que você irá ver que ele vai cair no erro.

Dá uma olhada no seu código catch…

na realidade, eu queria que ele mostrasse uma msg dizendo que nao poderia excluir pq tem associação, so que ele mostra “Excluido com sucesso.” mas nao exclui

Como você sabe que esse é seu erro se não aparece mensagem de erro algum?

pq só nao deleta se ele tiver associado, ex:

Unidade 1 - nao tem nada associado a ela [ deleta normal do banco ]
Unidade 2 - tem algo associado a ela [nao deleta do banco,mais mostra a msg “Excluido com sucesso.” ]

ErickRAR

Procure sobre CASCADE e veja qual seria o melhor tipo para você utilizar.

alepenchel

Eu queria obter o nome de todas as entidades associadas com a entidade à ser removida e que possuíssem dados.
Não encontrei uma forma simples de fazer isto com o hibernate como eu queiria, então apelei para os metadados do JDBC.

PS: Tenho um mapeamento do nomes de todas minhas tabelas com os nomes das entidades dentro do arquivo properties, pois o JDBC me retorna os nomes das tabelas e não das entidades.

Segue a POG!!!

private Set<String> getFKs(MinhaEntidade minhaEntidade) throws SQLException {
		Set<String> fks = new HashSet<String>();
		
		Session session = (Session)getEntityManager().getDelegate();
		SessionFactoryImplementor sfi = (SessionFactoryImplementor) session.getSessionFactory();
		
		Connection con = null;
		
		try {	
			con = sfi.getSettings().getConnectionProvider().getConnection();
		
			String schema = sfi.getSettings().getDefaultSchemaName();
			
			DatabaseMetaData meta = con.getMetaData();
			Table tabela = (Table) getEntityClass().getAnnotation(Table.class);
			ResultSet rsFK = meta.getExportedKeys(null, schema, tabela.name().toUpperCase());
			while (rsFK.next()) {
				String fkTableName = rsFK.getString("FKTABLE_NAME");
				String fkColumnName = rsFK.getString("FKCOLUMN_NAME");
				if (getEntityManager().createNativeQuery("select * from " + fkTableName 
						+ " where " + fkColumnName + " = " + minhaEntidade.getId())
							.getResultList().size() > 0 ) {
					String tabelaMessage = MessagesResourcesFactory.get(fkTableName.toLowerCase());
					if(tabelaMessage != null) {
						fks.add( tabelaMessage );
					} else {
						fks.add( MessagesResourcesFactory.get(tabela.name() + "." + fkTableName.toLowerCase()) );
					}
				}
			}
		} finally {
			if (con != null)con.close();
		}
		
		return fks;		
	}
Criado 1 de agosto de 2012
Ultima resposta 20 de set. de 2012
Respostas 11
Participantes 4