Exceção De Hibernate Genérica
O que acontece quando o Hibernate não sabe o que falar
Você pega uma exceção que é simplesmente um RuntimeException sem mensagem própria, ou uma GenericEntityException que vem embrulhada dentro de alguma outra coisa. Na prática, isso aparece quando o Hibernate tenta fazer alguma operação e o framework decide não criar uma exceção específica para aquele caso. A gente chama de exceção de hibernate genérica porque o Throwable não carrega informações suficientes pra saber exatamente onde errou. Eu já perdi duas tardes caçando esse tipo de problema num projeto legado com Spring Boot 2.7 e Hibernate 5.6. O erro vinha como uma javax.persistence.PersistenceException sem contexto, e a stack trace apontava só pro DAO. O problema real era um mapeamento errado numa relação ManyToMany com tabela intermediária que tinha coluna nullable mal definida. O workaround que funcionou foi colocar um breakpoint no método flush do EntityManager e inspecionar o SQL gerado antes da execução. Assim que vi o INSERT tentando botar NULL numa PK composta, o erro fazia sentido.
Diferença entre exceção de hibernate genérica e exceções específicas
As exceções do Hibernate seguem uma hierarquia que nem sempre é obedecida. Você tem JpaSystemException, NonUniqueResultException, NoResultException, ConstraintViolationException, e por aí vai. Quando cai numa exceção genérica, normalmente é porque o problema não se encaixa nos casos tratados pelo provider. Pode ser um erro de DDL, um constraint de banco não mapeado, ou até um bug interno do ORM. O insight que poucas pessoas mencionam é que a maioria dos desenvolvedores trata essas exceções com catch (Exception e), o que esconde informações preciosas. A stack trace original muitas vezes contém o endereço exato da falha no banco. Se você quiser ver algo útil, precisa desembrulhar a causa raiz com getCause() várias vezes até achar algo que tenha linha de códigoJava real.
Como identificar a origem real do problema
O primeiro passo é ativar o log de SQL do Hibernate. Coloque isso no application.properties: spring.jpa.show-sql=true, mais spring.jpa.properties.hibernate.format_sql=true. Com isso, você vê o comando que está falhando. Sem isso, você está apenas adivinhando. Depois, verifique as constraints do banco. Erros de unique constraint, foreign key violada, ou not null em coluna que deveria permitir vão aparecer como exceções genéricas. Eu costumo rodar um script SQL pra listar todas as constraints da tabela envolvida antes de perder tempo analisando o códigoJava. Outro ponto importante é o nível de log. Configure o logging do Hibernate pra DEBUG. A maioria das pessoas deixa só no INFO e perde mensagens críticas sobre o que o ORM está tentando fazer. O log mostra o SQL gerado, os parâmetros bindados, e às vezes até o plano de execução quando o problema é performance.

Cenários comuns que geram exceções genéricas
O primeiro cenário é conflito de versionamento. Se você tem duas entidades mapeadas pro mesmo nome de tabela com colunas diferentes, o Hibernate pode falhar silenciosamente até tentar persistir. O erro só aparece quando ele tenta executar o insert. O segundo é lazy loading em sessão fechada. Isso gera uma LazyInitializationException, mas em algumas versões do Hibernate ela vem embutida numa PersistenceException sem mensagem clara. Se você vê uma exceção sem mensagem que acontece durante uma busca, provavelmente é isso. O terceiro, e mais chatinho, é problema de tipos. Converter um BigDecimal pra int, ou um String pra date num mapeamento errado, pode gerar exceções genéricas de conversão. O Hibernate não valida tipos em tempo de compilação, então o erro só aparece em runtime.
Workarounds práticos que eu uso
Quando o erro é de constraint, a solução é ajustar o mapeamento. Verifique se todas as colunas que são PK ou têm unique constraint estão marcadas corretamente nas annotations. Use @Column(nullable = false) explicitamente, não confie no padrão. Para problemas de lazy loading, a alternativa é usar fetch join na query ou deixar a sessão aberta durante toda a requisição. O segundo enfoque é mais simples, mas pode trazer vazamento de conexão se não for bem gerenciado. Se nada disso funcionar, desabilite temporariamente o cache de segundo nível. Em alguns casos, lixo no cache pode causar comportamento estranho que parece exceção genérica. Coloque hibernate.cache.use_second_level_cache=false e teste.
Limitações dessa abordagem
O problema é que nem sempre dá pra capturar a exceção correta. Às vezes o Hibernate falha internamente e não gera nenhuma stack trace útil. Nesse caso, você precisa olhar o log do banco de dados diretamente, não do application. Outra limitação é que em aplicações distribuídas, a exceção pode vir de outro serviço. Um feign client falhando pode ser empacotado como uma exceção de Hibernate quando o Spring tenta transformar o resultado. Verifique se não há interceptor de transação confundindo a origem do erro. Se o problema persistir mesmo após todas as verificações, considere fazer upgrade do Hibernate. Versões mais novas têm melhor tratamento de exceções e mensagens mais descritivas. Mas isso não é sempre viável em projetos grandes com dependências travadas.

Galeria
-
Introdução ao Hibernate e NHibernate | PDF | Bancos de dados ... -
Common Hibernate Exceptions Explained | PDF | Information Science | Data -
PPT - Módulo II Persistência com Hibernate PowerPoint Presentation ...