Transaction utilizando DAO e DDD

10 respostas
M

Pessoal, estou estruturando uma aplicação para depois começar a produção em massa do modelo. O cenário é o seguinte:

Façades
Entity
RepositoryInterface
Repository

DAOInterface

DAOImpl
JPA
ORM
SGBD

Para montar esse amotoado de forma desacoplada estou usando DI com Spring.

Agora chegou a dúvida cruel. Como implementar transações. Em princípio, com pouca coisa implementada, fiz tudo dentro dos métodos dos DAOImpl. Mas sei que nem deveria ficar assim. Bom a dúvida é a seguinte:

Onde abrir a transação e onde fechá-la? Abro e fecho no Repository, deixando as várias chamadas a diferentes DAO’s dentro da mesma transação? Passo a transação como parâmentro para os daos?? Mas dessa forma, como desacoplar o repository do JPA ? Crio uma interface para transação? Injeto a transação? Como funciona o tal JTA ? É uma boa ? Tamém ouvi falar que o Spring poderia fazer isso com AOP, mas nem imagino como isso funciona… Até já li um pouco na documentação, mas me deu um nó…rs…

Não sei se estou falando bobagens, mas se alguém mais experiente puder ajudar, agradeço.

[]s.

10 Respostas

leonardobhbr

Amigo concerteza no DAO não é um bom lugar.

Na minhas aplicações utilizo uma camada Service que ela que valida as regras e encapsula os metodos do DAO, e ela que determina quando abrir ou fechar uma transação.

M

leonardobhbr:
Amigo concerteza no DAO não é um bom lugar.

Na minhas aplicações utilizo uma camada Service que ela que valida as regras e encapsula os metodos do DAO, e ela que determina quando abrir ou fechar uma transação.

Opa!

Poderia dar um exemplo prático para ajudar mais?

[]s.

M

Pessoal, pensei em fazer o seguinte:

Uma classe TransactionManager que estaria na camada de aplicação, criando id para as transações. Esta trnsação criada, chamaria um método na camada depersistêcia, que por sua vez teria um HashMap contendo transações com seus devidos apelidos.

Todo método que meus repositórios fossem acessar nos DAO’s estariam passando esse id de transação como parâmetro.

O que acham da solução?

abraços.

FernandoFranzini

Rapaz…quanta pergunta num post só kkkkkkk
Fica complicado ajudar…

Ponto principal é na sua camada de persistência…mas dependendo da arquitetura pode ser aberta em processos de negocio tb.

Sim…

Passar por parâmetros até da certo, mas deixa sua arquitetura poluída e engessada e inflexível.
A melhor forma de fazer isso é usando Thread-Local, deixando sua projeto llimpo e transparente.

Não tem como desacoplar…JPA é para ser usado dentro da sua camada de persistência! Mude seu ponto de vista - faça sua camada de persistência polimórfica para que possa intercambiar implementações diferentes de repository polimórficos. OU seja, o repositorio é usado justamente para encapsular detalhes de seu mecanismo de persistência adotados.

Depende vc vai fazer o controle de transação na unha ou vai algum framework?

Sim…mas só se seu projeto rodar em ambientes de container JEE completo…Seu projeto tem justificativa para isso? Senão vc pode usar outro framework mais ligth para fazer isso para vc…

Sim…spring é otimo !! ele internamente usa AOP com Thread-Local para gerenciar as transações recursivamente…eu só uso ele !!!
Mas vc tem estudar antes…

Segue uma dica - http://fernandofranzini.wordpress.com/2009/04/23/objetos-transacionais-em-java/

M

FernandoFranzini:
Rapaz…quanta pergunta num post só kkkkkkk
Fica complicado ajudar…

Caro Fernando, obrigado pela ajuda! Toda ajuda é bem vinda nessas horas. O fato é que minha única experiência é com transações dentro do DAO. Então, nessa nova arquitetura que estou tentando implementar, não fica legal.

Estou usando DDD (Domain-Driver Design), e uso o padrão Repository no domínio para abstrair o acesso aos dados, tratando à partir dele, apenas como repositorios de objetos. Só que os repositórios fazem acesso a interfaces de persistência que chamei de DAO’s. Porém, na camada de persistência, faço a implementação dos DAO’s usando qualquer infraestrutura de dados. Em princípio estou usando JPA como via de acesso. Porém, posso ter para uma mesma interface DAO, implementações diversas de DAO’s para JPA, Hibernate , JDBC ou até mesmo acesso a arquivos, por exemplo. Tudo isso transparente para o Repository e toda a camada Domain, pois simplesmente injeto o objeto na camada de domínio. Nunca havia usado o Spring e optei por ele para fazer DI, estou gostando mas não sei como usar seus recursos.

Então pensei, agora que o projeto deve crescer, em definir a estratégia de transações. Mas estou entendendo que uma transação não deve ser inicializada como uma iniciativa da camada de persistência, pois quem sabe o que deve ser atomizado é justamente o negócio. Nesse caso, entendo que o negócio (repository) deveria definir o que deve ser garantidamente guardado junto. Isso se não for ainda mais acima (acho que em alguns casos até pode ser), como em um outro objeto de negócio que acione vários repositórios de uma única vez e ele deva guardar tudo, ou nada.

Vc vê coerencia em meu pensamento?

Se eu optar pelo Spring gerenciar essas transações pra mim (uma opção considerável), será que encontro alugum material em português?

[]s.

FernandoFranzini

Eu discordo em varias partes…segue minha opinião para vc assimilar oque vc achar melhor para seu projeto:

  1. Repositório não chama os DAO!!! O repositório é um DAO nomeado para DDD!!! Vc fez 2 abstrações sem necessidade nenhuma…qualquer duvida já discutimos isso aqui http://www.guj.com.br/java/249971-padrao-repository

  2. Ponto de abrir transação é a camada de persistência sim.
    Por exemplo, seu repositorio tem metodos gravar, alterar e deletar…todos eles abrem transação.

  3. Alguns projetos com processos de negocio tb podem ter pontos transacionais que serão automaticamente propagados para todos as chamadas da camada de processo ou de persistência transparentemente. Vc pode fazer isso na unha, usando spring ou até mesmo ejb.
    Por exemplo o processo de transação bancaria teria um método chamado transferir que:

  4. Debitaria da conta 1 - > daoX.alterar();

  5. Creditaria da conta 2 - > daoY.alterar();
    Vc poderia marcar o ponto de transaççao nesse metodo que propagaria automaticamente e transparentemete para os 2 dao’s.

Eu tenho usado esses trés pontos acima citados nos últimos 6 projetos com muito sucesso.
Para detonar o Spring vc tem que parar tudo e ler pelo menos o Spring in Action.

M

FernandoFranzini:
Eu discordo em varias partes…segue minha opinião para vc assimilar oque vc achar melhor para seu projeto:

  1. Repositório não chama os DAO!!! O repositório é um DAO nomeado para DDD!!! Vc fez 2 abstrações sem necessidade nenhuma…qualquer duvida já discutimos isso aqui http://www.guj.com.br/java/249971-padrao-repository

Bom, esse é um assunto polêmico que tem gerado bastante discussão mundo afora… Ainda não tenho uma opinião formada sobre isso e na dúvida, preferi implementar separadamente.

No repository não aplico poliformismo, mas sim nos DAO’s.

Tenho uma interface para PERSISTENCE que acesso no repository e os DAO’s implementam essa interface. Por enquanto tá assim. No repository uso linguagem de domínio para definir métodos, enquanto nos PERSISTENCE uso linguagem padronizada mais tecnicamente. Posso colocar tudo em uma única classe? Sim, mas até ter segurança de que não vou usar, prefiro fazer implementações separadas. Se um dia achar que é melhor mudar, refatoro.

É o que faço hoje, mas espero que possa ser melhorado, pois é comum precisar fazer atomização de várias operações de repositório, ou seja, dentro do domínio.

Esse é o ponto! Espero encontrar uma maneira de abstrair a definição de “inicio de tranzação” em nível de domínio, para servir comumente aos métodos do repository, sinalizando para a persistência que as operações, a partir daí, devem ser atomizadas para que sua implementação interprete que isso é controle tranzacional. Como se os serviços de domínio criasse uma espécie de “id de unidade de ações de armazenamento” que seria repassado a camada de persistência que abriria a partir dessa “id” uma nova tranzação.

Gostaria de discutir esse assunto com os amigos para achar uma solução viável, ou para enfim chegar a conclusão de que estou equivocado em meu ponto de vista.

[]s.

FernandoFranzini

De qualquer forma, vc pode abrir transação aonde vc quiser, desde que ela seje propagada quando chamar algum objeto transacional! O spring vai te ajudar nisso.
No geral, toda decisão arquitetural deve ser tomada com base em obter o máximo de flexibilidade visando manutenção! Não existe uma decisão 100%! Sempre vamos ter que decidir algo, ganhar com seus prós e viver com os contras. O arquiteto/projetista é o cara que consegue visualizar isso la na frente!! Eu vejo que vc ja tem isso…parabéns!!! :smiley:
No caso do seu repositório, veja…
Quando criamos uma camada logica dentro da arquitetura de uma solução, ela serve para encapsular algum comportamento que não queremos expor no relacionamento para as outras…dessa forma isolada, podemos então dar manutenção ou intercambiar a camada dentro da ciclo de existência da solução sem propagar erros para as outras…isso é flexibilidade!!! Eu respeito sua opinião, mas o que eu quero q vc entenda é que essa suas 2 camadas de persistência (Repositorio -> DAO) não tem objetivo nenhum!! Ou seja vc ta fazendo a toa…muito pelo contrario, esta sobrecarregando sua arquitetura!
Veja que eu não sou contra…na verdade sou a favor desde que vc justifique o motivo.

M

FernandoFranzini:
De qualquer forma, vc pode abrir transação aonde vc quiser, desde que ela seje propagada quando chamar algum objeto transacional! O spring vai te ajudar nisso.
No geral, toda decisão arquitetural deve ser tomada com base em obter o máximo de flexibilidade visando manutenção! Não existe uma decisão 100%! Sempre vamos ter que decidir algo, ganhar com seus prós e viver com os contras. O arquiteto/projetista é o cara que consegue visualizar isso la na frente!! Eu vejo que vc ja tem isso…parabéns!!! :smiley:

Obrigado.
No caso, decidi implementar na unha um controle transacional na camada de aplicação. Vou fazer isso por julgar que o tempo que vou demorar para aprender o Spring (principlamente lendo e compreendendo o material em inglês) será o mesmo ou maior que se eu implementar na unha. Obviamente o ganho se eu aprendesse o Spring seria maior considerando que outros profissionais não precisariam aprender a interface que eu implemento. Porém farei com que seja algo relativamente simples e fácil de entender.

Quanto a isso vou ser mais declarado na justificativa:

Com uma interface para o acesso a camada de persistência, isolarei o repositório dela. Na camada de persistência terei classes que farão estritamente o “trabalho sujo” de implementar funções básicas de comunicação com ORM, JDBC ou outra interface. Já no repositório, espero construir uma linguagem mais próxima do domínio, independente de qual implementação de acesso a dados que vou usar, simplesmente encapsulando regras de armazenamento e busca de objetos que serão implementadas uma única vez para qualquer seja a implementação de acesso a dados que existir. Por exemplo, será transparente para o Repository, se estarei usando uma implementação JDBC, ORMx ou y ou File access. No método add(Permission SystemUserPermission) do PermissionsRepository, apenas obterei uma stockStorageUnit (tranzação), da camada de aplicação, injetarei dentro da entidade que será enviada ao método create(Permission SystemUserPermission) da interface SystemuserStorageController, criarei uma nova instância de PermissionEnabled, setarei seus atributos, inclusive a stockStorageUnit e enviarei ao método create(PermissionEnabled toEnablePermission) da interface PermissionEnabledStorageController. Fazendo isso, creio que de maneira relativamente simples, isolarei completamente a camada persistence da camada de negócios, sem tirar o controle da mesma.

o que acha?

[]s.

FernandoFranzini

Eu tenho que discordar, por que não foi essa motivação que eu entendi quando li o livro DDD ( veja as paginas 143 até a 147 falando do repository)
Veja que usando seu modelo sugerido, vc vai apenas replicar os mesmos métodos do DAO no REPOSITORIO…, tem 2 camadas diferentes, com 2 interfaces de serviço mas a do repositório ficaram sem sentido.
Acho que talvez vc poderia levantar essa discussão no forum do DDD, aonde os caras devem mandar bem…

Criado 26 de agosto de 2011
Ultima resposta 1 de set. de 2011
Respostas 10
Participantes 3