Parece que ficou no ar alguma duvida sobre DAO X Repository e que Repository pode ser / implementar um DAO (Data Access Object)
Repository (Repository) é onde as entidades estão. Não onde os “dados brutos” estão , mas os objectos de negocio. A entidade Cliente tem quantas instâncias ? Onde elas estão ? no repository. Como uma entidade encontra as entidades que lhe cabem ? Por exemplo , como um pedido encontra seus itens ? Pelo repositório. Claro que os itens são injetados no pedido, mas como ?
Pedido p = Repository.get ( Pedido.class, 14 ); // 14 é a chave
O Repositório internamente identifica que Pedido tem um associação com PedidoItem e automaticamente faz (internamente)
Pedido p = new Pedido(14);
p.setItens (Repository.get ( PedidoItem.class, p));
Ou poderia injetar uma implementação de Collection, que fizesse lazy loading
Pedido p = new Pedido(14);
p.setItens ( new LazyList( this, PedidoItem.class, p));
Que depois faria o codigo de cima quando alguém consultasse a lista.
Por outro lado, o repositório está associado ao dominio. Um DAO está associado aos dados brutos e à tecnologia paras os acessar (Data Access Object)
Mas como o repositório preenche os dados das instâncias ?
Ele tem que usar um DAO. Porque? Porque os dados não estão em objetos na memória. Mesmo que estejam, provavelmente não estão na mesma forma em que o domínio os quer. O comum é estarem no banco de dados, mas poderiam estar no mecanismo prevalente, ou numa simples List ( por exemplo em ambiente de teste)
O repository isola a instancia do dominio do local onde as outras instancias estão , o DAO isola o repositorio de saber onde os dados estão.
Veêm a diferença ? Um trabalha com instancias do dominio, o outro com dados brutos.
O DAO isola também o mecanismo de procura. Para bancos ele usa SQL, mas para list provávelmente usa um filtro. O repository apenas passa ao DAO “o quê ele quer” e não o “como encontrar”. O mesmo para os objectos de negocio que pedem o que querem e não dizem ao repository como encontrar.
Mas isto é a camada de negocios. Como seria na camada de visualização.
Se eu quiser listar todos os pedidos num table num html tenho que passar pelo repository ? Não. Basta usar o DAO. Não ha logica de negocios aqui. Apenas transferência de dados brutos.
O repositório é a forma como as instancias das entidades de negocio se comunicam e se encontram (repositório : onde todo o mundo está)
O dao é a forma como um repositório especifico executa esse trabalho.
Poderíamos ter repositório sem dao. Um exemplo classico é que o repositório seja um grafo gigante em que a raiz é um objeto anônimo que contém todas as coleções de todas as entidades de negocio que cotêm todas as referencias aos objetos que necessitam. Isso seria OO puro, mas isso não é tecnologicamente viável. Somos obrigados a guardar os dados de forma mastigada , e para isso que serve o DAO.
A interface de um DAO e de um Repository são muito semelhantes, mas elas não significam a mesma coisa. Não se pode pedir a um repository que encontre um objeto com base numa frase SQL, a um DatabaseDao, pode.
Mas a um InMemoryListDao não pode. Ou seja, a comunicação da intensão tb tem que ser abstraida de forma que o programador/objecto de negocio diga “o que quer” e "não como quer"
Claro que isto pode ser muito complicado, e, no caso geral serei obrigado a escrever o SQL na mão. Isto viola o encapsulamento que estou construindo com os DAO e os Repository. Isso nunca é bom. Claro, podem dizer que 99,99% dos casos usam banco de dados e que portanto usar SQL é tranquilo (quem diz SQL , diz EQL, HQL ,etc…) Mas , na verdade , é uma violação sim.
Quando no futuro , a tecnologia de persistência for outra, e o SQL não for mais a forma de procurar pela informação danou. Vai ter que haver outro software. Não se fizermos as coisas como deve ser. A lógica de negocio não depende do banco. Ela sempre será a mesma. Então se a tecnologia muda para outra coisa - digamos XQuery como exemplo - so teria que escrever um XQueryDAO. Mas e para as SQL que tive que escrever na mao ?
Para essas é criado um DAO especial que contém as SQL sofisticadas e retorna os dados. Ou seja, eu não passo o SQL , ele já está lá dentro. O repositório traduz isso para a camada de negocio. A camada de negocio não sabe que existem dois DAO no repositório. Mas ele sabe que DAO chamar dependendo da pergunta que lhe foi feita pelas classes de negocio. Se a tecnologia mudar eu crio um DAO com as consultas XQuery dentro dele e o repositório nunca saberá a diferença.
São duas responsabilidades diferentes. Ser o ponto de encontro das instancias das entidades - Repository, ou ser o cara que garimpa os dados avulsos que constituem essas entidades - DAO.
Alguem falou que um DAO generico seria algo como
Dao<T , I>{
T find (I id)
}
Na realidade o DAO mais genérico é
Dao {
<T> T find (Class<T> entity , Object id);
}
Que é o que o EntityManager do EJB 3 usa , embora ele seja um Repository e não um DAO.