Quando você chama um método fora de @Transactional
um bloco de transação, a transação pai continuará com o novo método. Ele usará a mesma conexão do método pai (com @Transactional
) e qualquer exceção causada no método chamado (sem @Transactional
fará com que a transação seja revertida conforme configurado na definição da transação.
Se você chamar um método com uma @Transactional
anotação de um método com@Transactional
a mesma instância, o comportamento transacional dos métodos chamados não terá nenhum impacto na transação. Mas se você chamar um método com uma definição de transação a partir de outro método com uma definição de transação e eles estiverem em instâncias diferentes, o código no método chamado seguirá as definições de transação fornecidas no método chamado.
Você pode encontrar mais detalhes na seção Gerenciamento de transações declarativas da documentação de transações de primavera .
O modelo de transação declarativo Spring usa proxy AOP. portanto, o proxy AOP é responsável pela criação das transações. O proxy AOP estará ativo apenas se os métodos na instância forem chamados de fora da instância.
will follow the transaction definitions given in the called method
. Porém, se a chamada vier da mesma instância do objeto, ela não terá nenhum efeito, pois a chamada não se propagará pelos proxies aop que são responsáveis pela manutenção da transação.@Transactional
definição de um objeto / instância diferente, então, embora o método de chamada tenha@Transactional
atributos diferentes , o método chamado seguirá a sua própria definição de transação.Isso depende de um nível de propagação . Aqui estão todos os valores de nível possíveis .
Por exemplo, no caso de um nível de propagação ser NESTED, uma transação atual será "suspensa" e uma nova transação será criada ( nota: a criação real de uma transação aninhada só funcionará em gerenciadores de transação específicos )
O nível de propagação padrão (o que você chama de "comportamento") é REQUERIDO . Caso seja chamado um método "interno" que
@Transactional
contenha uma anotação (ou transacionado declarativamente via XML), ele será executado dentro da mesma transação , por exemplo, "nada novo" é criado.fonte
@Transactional marca o limite da transação (início / fim), mas a própria transação está ligada ao encadeamento. Depois que uma transação é iniciada, ela se propaga pelas chamadas de método até que o método original retorne e a transação seja confirmada / revertida.
Se outro método for chamado com uma anotação @Transactional, a propagação dependerá do atributo de propagação dessa anotação.
fonte
O método interno afetará o método externo se o método interno não estiver anotado com @Transactional.
Caso o método interno também seja anotado com @Transactional com
REQUIRES_NEW
, o seguinte acontecerá.... @Autowired private TestDAO testDAO; @Autowired private SomeBean someBean; @Override @Transactional(propagation=Propagation.REQUIRED) public void outerMethod(User user) { testDAO.insertUser(user); try{ someBean.innerMethod(); } catch(RuntimeException e){ // handle exception } } @Override @Transactional(propagation=Propagation.REQUIRES_NEW) public void innerMethod() { throw new RuntimeException("Rollback this transaction!"); }
O método interno é anotado com
REQUIRES_NEW
e lança uma RuntimeException, de forma que definirá sua transação para rollback, mas NÃO EFEITARÁ a transação externa. A transação externa é PAUSADA quando a transação interna é iniciada e, em seguida, RETOMA APÓS a transação interna ser concluída. Eles são executados independentemente um do outro, então a transação externa PODE ser confirmada com sucesso.fonte