Abrindo novas transações dentro de métodos transacionais

É comum em processamento em lotes precisarmos tratar conjuntos de dados em transações separadas, com isso os frameworks mais conhecidos trazem o atributo REQUIRED NEW para simplesmente adicionarmos a anotação no método e o escopo da transação do método ser alterada.

Segue abaixo as formas de implementar a abertura de novas transações:

Em EJB

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void metodo(){

Java EE 7

@Transactional(Transactional.TxType.REQUIRES_NEW)
public void metodo(){

Em Spring

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void metodo(){

Agora como utilizar essa anotação para abrir novas transações dentro de métodos transacionais? Naturalmente iríamos separar as funcionalidades em métodos e adicionar Requires new no método que deveria estar em uma nova transação, como no exemplo abaixo.

public class ClasseX {
 
  @TransactionAttribute
  public void metodo1(List<Objeto> lista) {
      for(Objecto objeto : lista) {
         metodo2(objeto);
      }
  }

  @TransactionAttribute(REQUIRES_NEW)
  private void metodo2(Objeto objeto) {
     // faz uma ação com o objeto
  }
}

O resultado dessa solução é a execução do metodo1 com sucesso, no entanto novas transações não serão criadas nas chamadas do metodo2 e tudo será considerado em uma única transação, isso ocorre porque o metodo2 não passa pelo proxy do framework(EJB/Spring) por ser uma chamada local, dessa forma apenas o metodo1 passa pelo proxy e os dois métodos utilizam a configuração do metodo1.

A solução para que o metodo2 abra novas transações é a extração dele para uma nova classe para que a chamada do metodo2 não seja mais local e passe no proxy do framework, assim fazendo que a anotação do metodo2 seja considerada, como no exemplo abaixo.

public class ClasseX {

  @Inject
  private ClasseY classeY;
  
  @TransactionAttribute
  public void metodo1() {
    for(Objecto objeto : lista) {
       classeY.metodo2(objeto);
    } 
  }
}

public class ClasseY {

  @TransactionAttribute(REQUIRES_NEW)
  public void metodo2(Objeto objeto) {
    // faz uma ação com o objeto
  }
}

Observação: Os proxys gerados pelos frameworks são dinâmicos e utilizam a API de Reflection da JDK.

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.