Qual o problema de definir a transaction no DAO?
Qual o problema de definir a transaction no DAO?
Oi Giulia, tudo bem ?
O problema é que você fica com um escopo de transação muito fechado/curto. Vejamos um exemplo:
Dao
@Repository
public class ProdutoDao {
@PersistenceContext
private EntityManager manager;
@Transaction // abrindo no início da chamada e fechando no fim da chamada deste método
public void salva(Produto produto) {
manager.persist(produto);
}
public void qualquerOutraOperacao() {
// manager.fazQualquerCoisaNoBanco
// altera o estado da base
}
}
Veja que o salva()
define abertura e fechamento de transação. Caso algo dê errado no contexto dessa transação (qualquer exception lançada) automaticamente vai desencadear um rollBack não afetando o banco com mudanças indesejadas.
Controller (ou qualquer classe de Serviço que vai usar o dao)
@Controller
@RequestMapping("/produto")
public class ProdutoController {
@Autowired
private ProdutoDao dao;
@PostMapping
public String salva(@Valid Produto produto) {
// faz qualquer coisa relativa ao atendimento da requisição
this.dao.salva(produto);
return "redirect:/produto"; // manda pra lista
}
}
Até aqui tudo normal. Agora imagine que você precise pra essa action chamar qq outro método do Dao que altere a base, ou mesmo que nem seja no Dao, você poderia mandar a capa do livro pra um serviço de storage externo e dada uma resposta positiva você prossegue e salva no banco o produto com a url da capa, por exemplo.
@PostMapping
public String salva(@Valid Produto produto) {
// faz qualquer coisa relativa ao atendimento da requisição
storageService.salvaCapa(produto);
this.dao.salva(produto);
this.dao.qualquerOutraOperacao();
return "redirect:/produto"; // manda pra lista
}
Caso a capa não seja salva no serviço de storage o produto não deveria ser salvo no banco, nem a outra operação chamada. Mas da forma como se encontra, o save tem um contexto de transação que vai iniciar e fechar efetivando alterações de forma independente das outras ações. Escopo muito fechado.
Seria interessante então ao invés de cada ação do dao, ou do storage ter sua própria Tx, a própria ação do controller (ou qq outra lógica que os usa) ter sua transação. Com @Transaction no método do controller, ao invés dos métodos do Dao, conseguimos isso. Qualquer problema com a ação em geral, vai gerar um rollBack de todas as possíveis alterações :) Exemplo, qualquer problema com o serviço de storage o livro não será commitado no banco. Qualquer problema com a chamada a seguir do dao, vai dar rollback não efetivando o save do produto, mesmo ele tendo sido chamado antes, etc, etc.
Espero ter ajudado. Abraço!
Sim muito clara a explicação obrigado