Não org.hibernate.Transaction! Apenas lance exceções.
Autor: Marcos Oliveira | Publicado: 2011-01-03T05:07:00-08:00

A interface org.hibernate.Transaction obriga a implementação de métodos interessantes para o tratamento de transações, são eles: begin(), commit(), rollback(), wasRolledBack(), wasCommitted(), isActive(), registerSynchronization(Synchronization synchronization) e setTimeout(int seconds).Uma boa e comumente utilizada implementação dessa interface é JDBCTransaction. Porém essa implementação na minha opinião tem um pequeno problema que, embora não tenha prejuízos à e não interfira a execução correta do sistema, deveria ser corrigido, inclusive pretendo sugerir para a Hibernate Community um ajuste com relação a isso.Pule esse trecho se dominar o try/catch:Em java temos a opção de tornar nossa aplicação mais robusta através do bloco try/catch e do conjunto de exceções e classes que extendem java.lang.Exception. O try/catch também nos dá flexibilidade de criar e manipular nossas próprias exceções fazendo o tratamento de fluxos anormais do sistema. Isso pode ser usado, e frequentemente é, em Fluxos de exceções por exemplo, validações de negócio e outras ocasiões em que não se deseja seguir o fluxo normal do sistema.Veja rapidamente a sintaxe:try { //Executando algo perigoso (algo que pode lançar uma exceção declarada ou não) metodoPerigoso();} catch(MinhaExcecaoException e) { //Obrigatório no mínimo um catch por try //tratando exceção MinhaExcecaoException quando ela ocorrer} //Podem haver vários blocos catch, contando que as exceções mais restritivas venham antes das mais abrangentesfinally {//O bloco finally é opcional mas se for inserido sempre será executado, mesmo que nenhuma exceção seja lançada.}Agora veja em detalhes o que não gostei na implementação JDBCTransaction.Através de um SessionFactory ("Fabrica de sessões". Objeto responsável por oferecer sessões (nesse caso Hibernate), utilizando o Design pattern Factory para isso) obtive uma sessão e fiz o commit de uma transação:  final Session sessao = sessionFactory.openSession();  try {   sessao.beginTransaction();   final SQLQuery query = sessao.createSQLQuery("insert into TABELA_XXX values(?, ?)");   query.setParameter(0, "param1");// Exemplo de um parâmetro string, que será aplicado ao primeiro '?' acima   int param2 = 3L;//Só um exemplo de um parâmetro   query.setParameter(1, param2);// param2 será aplicado ao segundo '?'   query.executeUpdate();   sessao.save(entidade);//Fazendo outra transação, salvando uma entidade por exemplo.   sessao.getTransaction().commit();   sessao.flush();  } catch (final RuntimeException e) {   sessao.getTransaction().rollback();   //Faz outros tratamentos  } catch (final Exception e) {   sessao.getTransaction().rollback();   LOG.severe(e.getLocalizedMessage());  } finally {   fecharSessao(sessao);  }OK, tudo certo, se conseguir executar a transação tá ok, se der alguma exceção eu faço rollback, possivelmente registro log, e sempre havendo ou não erro, fecho a sessão.Mas se houver uma exceção eu mesmo quero tratar, da forma que eu quiser, não quero que nada seja feito além do que eu fizer. O problema que eu falei é que isto não ocorre.O sessao.getTransaction() do código acima retorna o objeto org.hibernate.Transaction que pode fazer o commit e quando há uma exceção, em algum lugar da pilha de métodos executada no commit() é chamado um printStackTrace.Esse método imprime na saída padrão, a pilha de exceções ocorridas. Por mais que eu queira tratar da minha forma, e a forma que quero não inclui a impressão do statckTrace, não há como fazer.De qualquer forma irá imprimir o printStackTrace caso haja uma exceção javax.sql.SQLException por exemplo.Por isso quando escrever um código, pense bem antes de colocar algo do tipo. Deixe que o programador trate do jeito que quiser, apenas lance a exceção.Afinal, se ele escrever algo como:try { metodoPerigoso();} catch (Exception e) {} //nada no bloco catchNão se preocupe, você não terá culpa disso! Um dia ele aprenderá de alguma forma que é melhor explodir a empresa em que trabalha do que fazer um código como esse!!!