Tentei… mas esses componetes que fazem uso do CGLIB sao confusos, segue abaixo parte da minha implementacao
/**
* Cerne do componente para controle de transacao. Faz uso de CGLib,
* uma biblioteca que provê mecanismos de manipulação de bytecode, permitindo
* implementar interfaces dinamicamente, interceptar a chamada de métodos.
* Chamando determinado método, interceptamos a sua ação, e verificamos se este método
* é transacional. Se for, abrimos uma transação, e executamos o método.
* Se ele for executado com sucesso, damos commit na operação.
* Porém, se der exceção, fazemos um rollback
*
* Isso se parece com a solução de Filtros Http, porém com uma vantagem:
* o controle transacional não fica misturado com a API do Controller (C do padrão MVC),
* e é mais flexível, pois não se prende ao contexto web
*
* Observe também que esta solução é melhor que tratar as transações diretamente nas classes Java.
* Isso porque você vai evitar muito código repetitivo (try, catch, commit, rollback, etc),
* e não vai ?poluir? inúmeras classes com este tipo de código.
* @author Ronildo
*/
public abstract class HibernateInterceptor implements MethodInterceptor {
private static final Logger logger = Util.startLogger(HibernateInterceptor.class);
/**
* O método intercept, proveniente da interface MethodInterceptor (CGLib), se encarrega
* de fazer o controle transacional. Veja que ele usa o HibernateHelper,
* e que o método transacional é explicitamente invocado, através de methodProxy.invokeSuper(),
* e o seu retorno é explicitamente devolvido
* @throws Throwable
*/
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if (isTransactional(object, method)){
logger.debug("logica de negocio deve ser executada dentro de uma transacao");
HibernateHelper.beginTransaction();
}
Object result = null;
try {
result = methodProxy.invokeSuper(object, args);
HibernateHelper.commitTransaction();
logger.debug("logica de negocio executada com sucesso");
}catch (Throwable e){
logger.debug("erro ao executar logica de negocio");
HibernateHelper.rollbackTransaction();
throw e;
}
return result;
}
/**
* Definido como abstrato para para obter máxima flexibilidade, pois apenas
* estendendo esta classe e implementando este método, podemos saber se o
* método é transacional ou não de diversas maneiras, como arquivos XML,
* arquivos texto, e anotações! (Esta classe é um caso do pattern Template Method).
*/
public abstract boolean isTransactional(Object object, Method method) ;
}
Eu nao entendo o momento em que o commit sera executado, parece que a rotina para depois de methodProxy.invokeSuper(object, args); e depois sem muito sentido ela e executada
O methodProxy.invokeSuper(object, args) invoca o método “de verdade”! E logo depois de terminar a execução dele haverá o commit.
Agora quanto a muitas transações abertas e fechadas… é uma transação por anotação. Tome cuidado para por a anotação no lugar adequado: geralmente em um façade para as operaões, por exemplo.