Tratamento de erros particulares em JDBC: SQLException

Pessoal,
o ponto é o seguinte: pra quem usa JDBC, sabemos que o SQLEXception encapsula diversos diversos diferentes de erro de banco, na verdade todos eles, tudo, é SQLException.
Daí é que vem: se quisermos saber se foi erro de chave duplicada, campo unique, etc etc, pra podermos tratar apropriadamente conforme o tipo do erro, analisamos o seguinte:
-> invocamos o getErrorCode() que retorna o inteiro correspondente ao codigo de erro que o banco lançou;
-> podemos também olhar o getMessage() do SQLException lançado, embora isso não seja nada confiável porque a mensagem poderia mudar.

O ponto é: ambos os modos não são confiáveis se pressupormos uma mudança de banco em uma aplicação, ou mesmo uma mudança de versão de banco! Para o MySQL, por exemplo, tem havdo diferenças nos códigos de erro com o decorrer das versões…
Então A PERGUNTA É:
alguem, alguma API, etc, já criou alguma camada de abstração que dê subclasses de SQLException ou algo assim visando explicitar melhor os tipos de erro de banco?
Exemplo: recebe um SQLException e automaticamente retorna um exception particularizado para o erro, tal que, com este, podemos fazer um tratamento mais apropriado conforme o erro gerado!

PS: eu sei que o Spring tem uma solução pra isso, mas eu queria mesmo é apenas o mapeamento do SQLException para o erro particular, sem ter que mudar toda a implementação de consultas, etc etc de sistemas já em produção!

Muito grato por vossa atenção e auxílios futuros.

mas a ideia é justamente eu não ter que fazer isso e nem ter que ficar dando manutenção, uma vez que já exista alguem ou alguma LIB que venha fazendo a mesma coisa!

Essa API não existe. Cada projeto desenvolve forma de trabalhar esse problema. O Spirng usa uma, o Hibernate usa outra, etc…

Se vc quer essa funcionalidade, vc precisa criar essa API.

Além dos codigos tem outras exceções como por exemplo IOException se não for possivel conectar-se ao banco. Esta precisa ser tratada em codigo.

O conceito é ter uma classe que faz as chamadas , quando dá um SQLException o sistema chama um objecto no padrão ExceptionHandler. Este objeto deve ser criado conforme o banco em uso ( Um Factory que crie este objeto com base no Connection). Esse objeto descobre qual classe de exceção mais especifica tem que lançar.

VC pode usar a API de metadados do JDBC para reconhcer qual o banco e o driver que está em uso. Com essa informação instancia a classe certa.

o uso fica algo assim


try {
 // algo que use jdbc

} catch (SQLException e){
     throw  exceptionHandler.handle(e);
}

Essa API não existe. Cada projeto desenvolve forma de trabalhar esse problema. O Spirng usa uma, o Hibernate usa outra, etc…

Se vc quer essa funcionalidade, vc precisa criar essa API.

Além dos codigos tem outras exceções como por exemplo IOException se não for possivel conectar-se ao banco. Esta precisa ser tratada em codigo.

O conceito é ter uma classe que faz as chamadas , quando dá um SQLException o sistema chama um objecto no padrão ExceptionHandler. Este objeto deve ser criado conforme o banco em uso ( Um Factory que crie este objeto com base no Connection). Esse objeto descobre qual classe de exceção mais especifica tem que lançar.

VC pode usar a API de metadados do JDBC para reconhcer qual o banco e o driver que está em uso. Com essa informação instancia a classe certa.

o uso fica algo assim


try {
 // algo que use jdbc

} catch (SQLException e){
     throw  exceptionHandler.handle(e);
}

[/quote]

olá,
não vejo qualquer dificuldade para fazer by myself. o problema não está ai.
o ponto que quero frizar é: se por um acaso o Spring DAO ou outra solução já tem isso PRONTO, não seria possível eu simplesmente usar? É isso que eu queria, uma indicação de uma solução pra apenas usar, onde nesta solução por exemplo já haja o mapeamento dos códigos de erro para exceções específicas! Acho que o problema está claro.
Não veria sentido em eu ter que fazer e manter algo que a principio ja esteja sendo feito e mantido por alguma solucao.

1 curtida

[quote=icarocd]
olá,
não vejo qualquer dificuldade para fazer by myself. o problema não está ai.
o ponto que quero frizar é: se por um acaso o Spring DAO ou outra solução já tem isso PRONTO, não seria possível eu simplesmente usar? É isso que eu queria, uma indicação de uma solução pra apenas usar, onde nesta solução por exemplo já haja o mapeamento dos códigos de erro para exceções específicas! Acho que o problema está claro.
Não veria sentido em eu ter que fazer e manter algo que a principio ja esteja sendo feito e mantido por alguma solucao.[/quote]

  1. Vc está supondo que foi feito corretamente
  2. Vc está supondo que será mantido
  3. Vc está supondo que não se deparará com casos especiais não tratados pela solução de terceiros.

Se pode usar o Spring e não se preocupar com isto. Mas terá que usar “todo” o Spring, não apenas o ExceptionHandler (aliás porque não ha um o tratamento está embutido no proprio Spring). Vc terá que usar o canhão para matar a mosca…

Fala Ícaro, blz?
Cara estou com o mesmo problema aqui no trabalho, estou pensando em fazer a minha própria solução. Porém se já existe alguma API ajudaria bastante.
Como você resolveu esse problema?

Obrigado,

[quote=jrsilvanio]Fala Ícaro, blz?
Cara estou com o mesmo problema aqui no trabalho, estou pensando em fazer a minha própria solução. Porém se já existe alguma API ajudaria bastante.
Como você resolveu esse problema?

Obrigado,

[/quote]

Silvanio,
Na epoca do problema eu acabei resolvendo com uma solução caseira mesmo pois que vi o uso do Spring (JDBCTemplate) até ajudaria mas eu teria que mudar muito a aplicação.
Por outro lado, se hoje eu voltasse a precisar usar JDBC certamente eu usaria a API do Spring porque ela auxilia várias coisas: tratamento de erros uniformizado, auxilio a binding de consultas, pool, etc.

Ícaro,

obrigado pela a dica, vou fazer uma solução caseira também.

vlw.

Porque não utiliza o conceito adotado pelo Spring?

Bem resumidamente, o Spring mapeia os erros de acordo com o fabricante (vendor) de cada banco de dados em um XML, separado por categoria de erro.

Mais ou menos, o XML teria essa estrutura:

<bean id="Oracle" class="org.springframework.jdbc.support.SQLErrorCodes">
 <property name="badSqlGrammarCodes">
  <value>900,903,904,917,936,942,17006</value>
 </property>
 <property name="invalidResultSetAccessCodes">
  <value>17003</value>
 </property>
 <property name="dataAccessResourceFailureCodes">
  <value>17002</value>
 </property>
 <property name="dataIntegrityViolationCodes">
  <value>1,1400,1722,2291</value>
 </property>
 <property name="cannotAcquireLockCodes">
  <value>54</value>
 </property>
</bean>

Da uma lida aqui, principalmente nos tópicos JDBC Exception Handling e Handling Vendor-Specific Error Codes.

Mapeando as categorias de erros dessa forma, voce consegue lançar uma exceção interna da sua aplicação.