Tratamento de Exceções - JPA - Hibernate

8 respostas
E

Pessoal,

Estou desenvolvendo um sistema, e pintou a seguinte dúvida, no uso do Hibernate (JPA):

Qual a exceção é lançada quando ocorre uma violação de constraint? No caso um dos atributos da minha Entity tem as seguintes constraints: @Column(name = “nome”, nullable = false, unique= true)

O banco de dados está obedecendo corretamente às constraints… A dúvida é para o tratamento das Exceptions, e mostar ao usuário mensagens amigáveis:

No caso de tentar : entityManager.persist(entity); é lançada a exceção javax.persistence.EntityExistsException… Neste ponto está OK… Estou tratando corretamente…

Agora quando tento: entityManager.merge(entity);é disparada uma exceção diretamente pelo Hibernate (org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update )… Para não tornar meu código amarrado ao Hibernate, qual exceção eu deveria capturar neste caso??

Feliz Natal a todos!

[]s
Erick

8 Respostas

Y

Eu nao posso te afirmar com 100% de certeza, mas acho que ConstraintViolationException é lancada quando ocorre erro de constraint no banco. Talvez seja alguma que esteja “escapando” do tratamento no mapeamento, mas que esteja no BD.

Tente ver qual a exception que causa o erro, a mensagem deve indicar onde esta o problema.

E

A violação de Constraint foi forçada…

Eu inseri um registro no banco
Depois alterei um outro registro, de modo que o valor do campo “nome” ficasse igual ao primeiro registro… Como existe a constraint UNIQUE, o banco de dados não deixou que o UPDATE ocorresse… Esse era o comportamento esperado mesmo…

Essa é uma situação que pode ocorrer no “mundo real”… O usuário tentar dar update em uma Entity e acabar esbarrando em uma constraint… Então precisamos tratar isso de forma apropriada, para exibir mensagens de erro coerentes…

o que eu quero evitar é ter que fazer:

try{
  entityManager.merge(entity)
}catch (Exception e){}

No caso do usuário tentar inserir um registro novo no banco… e esbarrar em uma constraint consigo capturar a exception dessa forma:

try{
   entityManager.persist(entity);
} catch (javax.persistence.EntityExistsException e){}

Não estou encontrando uma forma funcional de capturar essa Exception… O ideal seria ter uma Exception do proprio javax.persistence… Amarrar numa exceção do Hibernate não é legal, porque o código vai ficar dependente do Hibernate… A idéia do JPA é justamente permitir a troca do Persistence Provider, então não faz muito sentido eu amarrar em uma Exception do Hibernate…

Alguém já se deparou com esse problema? Idéias??

Y

Eu nao sei pq nunca trabalhei somente com JPA, mas acho estranho ela nao ter um “wrapper” para essa exception.

O que voce poderia fazer é ver a possibilidade de pegar as excecoes desse tipo num ponto comum e lancar uma excecao “customizada”, dessa forma apenas uma pequena parte do codigo estaria atrelado ao hibernate e nas camadas superiores vc faria referencia a essa sua excecao. Isso contornaria o problema, pelo menos até uma solucao da JPA.

C

Eu ainda fico realmente impressionado com este tipo de coisa. A pergunta do colega foi clara, direta, prática e objetiva e, infelizmente, as respostas passam bem longe; além de retóricas, são evasivas.

Mesmo assim, ainda vou esperar alguma resposta inteligente de algum gurú que realmente consiga entender perguntas pois estou também com esta dúvida.

E depois me acusam de provocar flames nas listas.

Bom dia a todos.

C

pessoal estou com um caso assim e para funcionar com o merge usei assim

try {
em.merge(entity);
em.flush();
} catch(PersistenceException e) {
//  e aqui tratei minha exception usando uma namedQuery buscando pela minha unique key
// caso encontre dou uma msg amigavel ao usuário.
}

obs. Mais gostaria de uma solução sem o flush. Abri até um link já sobre isso http://www.guj.com.br/posts/list/199974.java

F

voçê conseguiu a solução?

J

Olá!
Você conseguiu capturar corretamente a exceção?

W

Galera desculpa ressuscitar o tópico mas é porque eu encontrei uma solução depois de horas e horas de pesquisa no google e dei uma modificada pra funcionar do jeito que eu necessitava, vou deixar aí pra caso alguem precise:

no meu método da classe controller/DAO/onde faço o persist no entity manager coloquei throws Exception e coloquei um try catch com esse catch:

catch (PersistenceException e) { Throwable t = e; boolean cont = true; while (t != null) { if (t.getMessage().startsWith("Duplicate entry")) { cont = false; throw new Exception("Duplicate entry"); } t = t.getCause(); } if (cont) { throw new Exception(e.getMessage()); } }

e la no meu managedbean coloquei o seguinte catch no metodo salvar:

catch (Exception e) { if (e.getMessage().trim().startsWith("Duplicate entry")) { Msg.show("Cpf/Cnpj está repetido!"); } else { Msg.show("Erro ao Salvar"); e.printStackTrace(); } }

tomara que seja de ajuda pra alguem, falou!

Criado 24 de dezembro de 2008
Ultima resposta 26 de mar. de 2013
Respostas 8
Participantes 7