Se você tá chamando “commit()” no Dao, qual a diferença de chamar “commit()” no banco? O que foi que você abstraiu fazendo isso? A lógica do banco de dados está vazando pro código cliente, que nem deveria saber que tem um banco relacional “do outro lado do espelho”.
Se você quer algo concreto, é só ver tudo o que já foi falado sobre ThreadLocal e filtros nos últimos dias, ou dar uma olhada no controle de transações do Spring:
Não é correto colocar o controle dentro do seu DAO, mesmo pq, se você precisar de uma transação que envolva mais de um DAO, vc tá ferrado.
Eu fiz algo assim:
Transaction t = TransactionManager.beginTransaction();
try {
dao1.save( x );
z =dao99.select( 1 );
dao666.update( z );
dao12345.delete( www );
t.commit();
} catch( Exception e ) {
t.rollback();
} finally {
t.end();
}
Internamente usei ThreadLocal. Meus DAOs pegam a conexão da transação que é compartilhada por eles, via ThreadLocal. Caso não exista uma transação, ele pega um conexão default do DAO.
A conexão retornada pela Transaction é uma casca sobre a Connection original, pois eu desativei coisas como commit(), rollback() e close(), delegando esta função para a Transaction. Por isso é obrigatório chamar o t.end().
O que você sugere, numa aplicação web, por exemplo, é que toda a ação do action, em um request, é uma transação, correto?
Ao meu ver isso prende demais a gente. Posso ter mais de uma transação ocorrendo no meu negócio e quero poder ter este controle.
Pelo menos meu código de negócio sabe onde começa e termina sua transação. O que fiz foi simplesmente achar uma forma de desacoplar e abstrair o uso de transação para um modelo mais genérico do que acessar recursos indevidamente, além de ser uma forma mais elegante de controle.
Como em EJB você pode criar um método que atenda a uma nova transação, mas como não uso EJB, fiz usando essa camada de controle.
Então, depende da empresa/gestor, é complicado. Se eles fecham um escopo de tecnologia, é bem difícil sair daquilo e usar outras coisas. Ainda mais em grandes empresas com grandes projetos. Eles têm de gerenciar os detalhes, e é aí que às vezes podem limitar nossa capacidade e inovação.
Lá eu consigo usar muita coisa nova. Eu, quando posso, fica colocando algo pra ajudar, mas não fico inventando muito fora daquilo, ainda mais pq usamos um framework in-house, que fede.
Como nunca usei AOP, não fico tentando inventar e, de repente, perder muito tempo aprendendo algo que pode fadar ao fracasso.
Nops, só o estágio e um projeto de pesquisa mesmo.
Vixe, framework próprio é uma coisa complicada. Uns amigos fizeram um framework MVC pra o estágio deles mas no fim a coisa ficou muito complicada e quando eles saíram a galera que entrou “dançou beleza”, porque ficou amarrada a uma coisa não tão bem feita (agente ainda é estudante né :lol: ) e que só tem manutenção lá dentro.
Eu não acho que seja uma boa investir numa coisa dessas se for absolutamente necessário e não houver nenhuma outra opção decente que possa ser usada ou adaptada.
Acho que isso é até uma vantagem do meu estágio, o povo só quer a coisa pronta, não interessa como. Comecei com Struts/Hibernate/JSP/Velocity, agora tô terminando uma migração pro Hibernate 3, colocando o Spring junto com o Struts e eu espero anter de terminar migrar tudo pro Spring MVC. Lá eu to botando a teoria na prática e tá valendo muito a pena, esse negócio das transações “externas” eu botei em prática lá, são as minhas cobaias :mrgreen:
[quote=danieldestro]
Como nunca usei AOP, não fico tentando inventar e, de repente, perder muito tempo aprendendo algo que pode fadar ao fracasso.[/quote]
Sei não velho, AOP não é a resolução pra todos os problemas, mas esse tipo de “interceptação” é uma das especialidades, dá uma olhada no AspectJ, pode ser que te ajude numa outra coisa que não tem nada haver com isso
Esse FMK in-house foi feito em 99 ou 2000. Cara, é uma grande lástima da minha vida. O cara que o fez, simplementes fez uma versão para quase cada um dos projetos existentes. Isso que alguns migram de plataforma e temos que trocar o FMK. É um Deus nos acuda. Um saco!
Por isso já tô de saco cheio. Quero inovar, por coisas novas, inventar, e não me limitar. Para isso acho que preciso mesmo pôr em prática a minha consultoria e projetos próprios. Logo, logo!
Sobre o AOP, eu tô ligado, mas qdo se tem prazos e limitações, inovar não é a “melhor” solução.
[quote=Maurício Linhares]O código cliente tem que inicializar as transações Daniel? Não seria melhor que isso fosse feito externamente não? Usando interceptors?
O controle saiu de dentro do DAO mas foi parar no código que usa diretamente os DAOs, não parece melhorar muita coisa não.[/quote]
Olá, desculpe por interromper a conversa de vocês sobre fmk, empresas e outras coisitas… mas queria aproveitar a colocação acima do Maurício para tirar uma dúvida!
Bom, a questão é a seguinte.
Se eu ficar amarrando o início da transação e o término dela em um interceptor, filtro, ou seja lá o que for acho super bacana. No entanto, e quando inicio uma transação que só irá fazer um select all?? Para isso eu não precisaria de uma transação!
Como vcs lidam com isso? Vcs iniciam um transação assim mesmo, ou em caso de consultas vcs não iniciam a transação?
Se Vocês não iniciam a transação, então como vcs fazer para controlar isso?
[quote=Thiago Senna] Se eu ficar amarrando o início da transação e o término dela em um interceptor, filtro, ou seja lá o que for acho super bacana. No entanto, e quando inicio uma transação que só irá fazer um select all?? Para isso eu não precisaria de uma transação!
Como vcs lidam com isso? Vcs iniciam um transação assim mesmo, ou em caso de consultas vcs não iniciam a transação? [/quote]
Eu sempre inicio uma transação, mesmo que seja pra um select.
Gerenciar as transações fora dos DAOs permite você usar mais de um DAO sem muita dor de cabeça.
E para evitar ficar repetindo o código de gerenciamento de transações faço o mesmo que com statements e resultsets, uso um Command.
Crio um TransactionalCommand e mando executar ele dentro de um contexto transacional ou não. Veja que é possivel inclusive proteger de ter uma action que deveria ser read-only modificando a base. Fazendo wrapping da Connection como o Destro sugeriu.