Servlet + JDBC (commit e rollback)

Em um servlet recebo os dados do formulário, crio o objeto e envio ao DAO para cadastrar no banco de dados com JDBC…

Local local = new Local();
local.setEndereco(req.getParameter(“endereco”));

local = localDao.insert(local); //retorna o local com o id gerado do banco

Produto produto = new Produto();
produto.setId(Interger.parseInt(req.getParameter(“id”)));
produto.setNome(req.getParameter(“nome”));
produto.setLocal(local);

produto = produtoDao.insert(produto); //retorna o produto com o id gerado do banco

Estou tendo problema que o Local é cadastrado no banco corretamente… mas quando encontro erro no cadastro do produto no banco… preciso fazer um rollback inclusive no produto…

No insert() do localDao faço o commit e se der erro o rollback…a mesma coisa para o produtoDao… mas preciso fazer o rollback no local se o produto der erro… colocar o insert do local junto com o insert do produto não vejo como uma boa opção…ate pq tenho momentos que nao preciso inserir produtos com local…

Veja se o exemplo pode te ajudar.

Depois que instanciar a conexão, configure:

suaConexao.setAutoCommit(false);

E na hora dos seus inserts:

try {
    //INSERT 1...
    //INSERT 2...
    suaConexao.commit();
} catch (Exception e) {
    suaConexao.rollback();
    throw e;
}

O commit não deve ser feito no DAO a cada instrução mas sim após todas as instruções serem efetuadas com sucesso.

Deves ter uma camada acima do DAO que é responsável por gerir a transação:

  • abre transação
  • invoca todas as instruções nos respetivos DAO (insert/update/…)
  • rollback se alguma instrução deu erro
  • commit da transação se todas as instruções executaram com sucesso

O grande problema é que meus inserts são separados em DAOs… e o DAO que conhece a minha conexão… e quem chama os DAOs separados é a servlet que não conhece a conexão…

Usando Servlet… antes de chamar o DAO eu teria que manualmente acionar essa camada para abrir a transação ne??.. e depois manualmente commitar ou dar rollback …

Não necessariamente. Com tens agora a tua arquitectura? EJB? Spring?

Está certo a parte dos DAOs separados, onde coloquei no comentário INSERT 1 e 2 entrariam suas chamadas de inserts que já estão nestes DAOs. Não é para mexer nisso. O problema é que você disse agora que está fazendo tudo isso no servlet, não é local adequado, mas sim na sua classe de negócio.

Pois é… não… Servlet não mão…

Veja o que acha de um caminho que pensei aqui: Eu tenho um DAO (abstrato) que no construtor…inicio a conexão com o banco… nesse DAO eu poderia ter métodos de commit e rollback… pq ai o Servlet conheceria esses métodos… e conseguiria dar o commit ou rollback quando for necessário… seria uma boa?

Não entendi… no servlet… eu faço produtoDao.insert(produto) e localDao.insert(local)… nao é na servlet que devo chamar o Dao?

O “servlet” só deve fazer o meio de campo para atender a requisição, não deve ficar com a responsabilidade de saber quantas inserções serão necessárias no banco de dados.

Então o servlet deve receber os dados do formulario e mandar pro produtoDao? e o produtoDao deve saber se é necessário incluir um local ou não? E nos casos que preciso incluir um produto Sem local? O produtoDao verificaria, estando nulo faço a inserção sem local, não estando nulo vejo se existe, se não existir cadastro também o local? Seria isso?

O Servlet deve receber os dados do formulario, coloca numa entidade e mandar para um service/business e esse sim, abre transação, sabe toda a lógica do que é ou não necessário e chama os daos, devolvendo no final a resposta para o servlet.

O Dao continua fazendo operações individuais para o banco de dados. A classe de Negocio que vai concentrar como será atendido a funcionalidade.

1 curtida