Clique aqui para ler esse artigo em PDF.
Hibernate e AspectJ
Gerenciando transações de forma 100% transparente
Aprenda como criar um módulo de controle transacional robusto, reutilizável e completamente transparente à aplicação
De que se trata o artigo:
Gerenciamento de transações no Hibernate utilizando AspectJ. Apresentamos como criar aspectos capazes de tratarem tudo o que diz respeito ao gerenciamento de transações sem a necessidade de alteração no código responsável pelas regras de negócio.
Para que serve:
Prover uma forma 100% transparente de gerenciar as transações em sistemas que utilizam o Hibernate como framework de persistência. Para isso, criamos um conjunto de classes de controle transacional reutilizáveis que podem ser facilmente adicionadas a qualquer sistema Java.
Em que situação o tema é útil:
As transações então presentes em grande parte dos sistemas, portanto, dispor de um componente para gerenciamento de transações que seja facilmente reutilizável agiliza bastante o desenvolvimento do software.
Hibernate e AspectJ:
No desenvolvimento de sistemas, é bastante comum a necessidade de implementar algum tipo de gerenciamento de transações. Esse gerenciamento pode ser feito de diversas formas, porém, grande parte delas deixa o código que o utiliza acoplado, de alguma maneira, a esse serviço. Utilizando a programação orientada a aspectos (AOP), por meio da linguagem AspectJ, isso pode ser feito de maneira transparente. Com o uso de aspectos, todo o código relativo ao controle transacional fica isolado. Só é preciso, então, informar que partes do código principal (o qual contém as regras de negócios) devem ser interceptadas pelo código dos aspectos. Isso tudo é feito sem a necessidade de alterar uma linha do código principal. Utilizando esse recurso juntamente com a API de anotações de Java, é possível criar um componente reutilizável capaz de gerenciar transações em um sistema qualquer.
Gerenciar transações de forma eficiente e não intrusiva é uma tarefa que ainda causa muita dor de cabeça para o desenvolvedor. Neste artigo veremos como esse problema pode ser resolvido de forma simples quando utilizamos os recursos providos pela programação orientada a aspectos.
É muito comum, no desenvolvimento de sistemas, nos depararmos com requisitos que exigem uma seqüência de operações a serem realizadas de forma atômica, ou seja, onde apenas o resultado do todo faz sentido. Nesse tipo de cenário, quando qualquer operação do conjunto falha, o conjunto inteiro deve falhar. Um exemplo clássico é o da transferência entre contas de um banco, onde as operações de débito na conta origem e crédito na conta destino devem ter sucesso por completo ou falhar por completo.
Um dos benefícios[1] do conceito de transação em banco de dados é exatamente o de prover essa capacidade de restaurar o estado anterior dos dados, caso ocorra alguma falha dentro do contexto transacional. Na realidade, isso é possível porque os dados não são persistidos, de fato, até que a transação seja confirmada através do comando commit, ou seja, enquanto a transação não for commitada esses dados ficam numa área de armazenamento temporária – o “log de transações” – que é visível apenas à sessão corrente, mas não aos demais usuários do BD.
Para gerenciar transações no Hibernate, nos é fornecida a interface org.hibernate.Transaction com métodos como beginTransaction(), commit() e rollback(). Com a ajuda desses métodos e do mecanismo de tratamento de exceções de Java é possível demarcar o escopo transacional facilmente. Vejamos na Listagem 1 como ficaria um pseudo-código onde vários métodos são chamados num contexto transacional.
Listagem 1. Pseudo-código: métodos sendo chamados num contexto transacional
try {
transaction.beginTransaction();
metodo1();
metodo2();
...
metodoN();
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
Contudo, veremos que implementar um controle transacional robusto e que não prejudique a coesão dos módulos da aplicação nem sempre é uma tarefa fácil. Neste artigo aprenderemos a implementar o gerenciamento de transações de uma forma simples, robusta, transparente e reutilizável. Para isso utilizaremos recursos da programação orientada a aspectos, através da linguagem AspectJ.
Aplicação Exemplo
Para que possamos praticar e validar nossa solução à medida que formos discutindo, este artigo será baseado numa aplicação exemplo que tratará do caso clássico do sistema bancário com suporte a transferência entre contas, uma vez que este deixa bem clara a importância de um controle transacional bem definido. No nosso sistema será possível efetuar operações de crédito, débito e transferência em contas bancárias. Vamos dar uma olhada no que seriam os principais requisitos da nossa aplicação:
1.O sistema deve possuir operações para crédito e débito em contas bancárias;
2.Para a operação de débito, o saldo da conta deve ser maior ou igual ao valor que se deseja debitar. Caso essa condição não seja atendida, a operação deve ser abortada e um erro deve ser gerado;
3.O sistema deve prover a funcionalidade de transferência entre contas e esta funcionalidade deve simplesmente encapsular as operações de crédito e débito;" [...] continue lendo...