Pra quê um monte de DAOs cheios de métodos?

82 respostas
Mauricio_Linhares

Opa galera,

Eu tava escrevendo umas coisas aqui pra colocar num material sobre o Hibernate e uma das partes seria mostrar como implementar um DAO usando o Hibernate. Me baseando numa implementação de um sistema que eu estou desenvolvendo aqui na universidade, terminei esbarrando em uma das diretivas do padrão, a definição de um método para cada query feita no banco.

Sendo uma implementação feita com o Hibernate, eu pensei em não seguir o padrão nessa onda de “um método pra cada query”. Criei um DAO genérico, que insere, atualiza, deleta, lista e busca usando “exemplos” e dentro desse mesmo DAO coloquei mais um método, executarBusca a assinatura ficou assim:

O parâmetro String é apenas o nome da Named Query que foi definida lá nos arquivos de mapeamento e o Map é o conjunto de pares “nome-parâmetro” da query. Por exemplo, a query pode ser:

Então eu colocaria um objeto no Map assim:

O próprio método se encarregaria de colocar o parâmetro lá.

Fazendo desse modo, a quantidade de código a ser mantido diminui de uma maneira drástica, porque eu não vou mais precisar escrever um método pra cada select, a maioria deles vai estar definida como Named Queries nos arquivos de mapeamento do Hibernate.

Eu pensei em criar métodos de busca nos DAOs quando fosse necessário usar código específico de um banco ou quando as pesquisas fossem feitas usando a Criteria Query API.

Alguém tem alguma idéia sobre alguma outra maneira que isso poderia ser feito? Alguém já fez coisa parecida?

[editado]Editei no nome pra ficar mais relacionado ao assunto né[/editado]

82 Respostas

Z

O problema é que você está forçando a classe que está usando o DAO a saber detalhes da persistência (nesse caso, saber o nome da NamedQuery), quebrando o conceito de DAO. E isso é feio, tão feio quanto passar um SQL pra um DAO non-hibernate. Só pq é uma namedQuery, e vai usar hibernate, não torna mais bonito. :D

Com o sono que eu tou, a única sugestão que eu posso dá é você tornar o executarBusca() como private, criar métodos que recebam um mapa de parametros, chame o executarBusca() passando a namedQuery preterida e os parametros.

private List executarBusca(String namedQuery, Map parametros) {
...
}

public List buscarAlgumaCoisa(Map parametros) {
    return executarBusca("namedQueryParaBuscarAlgumasCoisas", parametros);
}
Mauricio_Linhares

Mas assim ele ainda vai ter que saber o nome do método.

E se eu for inserir paginação? Vou ter que fazer o overload de todos os métodos passando também os parâmetros da paginação?

Eita padrão complicado danado… :shock:

Z

Não entendi. É um problema a classe que está usando o DAO saber o nome de um método desse DAO?

É o preço a ser pago para se ter um método super-fantástico-faz-tudo-da-estrela. Mas… pq não?

Mauricio_Linhares

Saber o nome do parâmetro não seria praticamente a mesma coisa de saber o nome do método não?

Um método pra cada select é tanto código pra se manter… :shock:

Z

No exemplo simplista que eu dei, seria “praticamente” a mesma coisa.

Invés de um hiper-método que já fizesse a consulta, você poderia ter um que retornasse um objeto Query, daí quando precisasse de mais algum tratamento na consulta (como paginação) faria no método.

public List buscarAlgumaCoisa(Map parametros, int inicio, int quantidade) { Query query = superMetodoQueCriaObjetoQuery("namedQuery", parametros); query.setFirstResult(inicio); query.setMaxResults(quantidade); return query.list(); }

Exemplo que pode ser usado pra responder a primeira pergunta! :wink:

Z

Relendo o tópico inicial, vi que a sugestão que eu dei não soluciona o seu problema, que é ter muitos métodos no DAO. :roll:

Mas o problema é ter muitos métodos ou é ter muito código dentros desses métodos? Você quer abstrair todo o trabalho de passagem de parametros para a consulta, deixando os métodos mais limpos, ou simplismente limpar a interface da classe, deixando com poucos métodos?

Mauricio_Linhares

O problema é ter muitos métodos que fazem exatamente a mesma coisa. Praticamente todos vão ter as mesmas chamadas, sendo passados do mesmo jeito e ainda vai ter o problema da paginação, onde todos os métodos vão ser sobrecarregados pra ter o contador do primeiro registro e a quantidade de registros que ele deve receber.

No padrão DAO, agente coloca vários métodos pra conseguir independência do banco ou de como as informações vão ser serializadas, só que usando o Hibernate, eu já tenho meio caminho andado, não vou mais me preocupar tanto com independência de bancos de dados.

Será que é realmente necessário seguir o padrão, se a proposta dele já está sendo cumprida?

pcalcado

Maurício,

Entendi sua sugestão, mas tenho problemas.

Vamos abstrair mais. Imagina que eu possua umas constantes:

BUSQUE_POR_NOME
BUSQUE_POR_IDADE
BUSQUE_POR_SEXO

E que estas sejam utilizadas para achar as queries no seu arquivo (dá pra fazer em SQL também, colocando queries em properties).

E um método:

public List buscar(int query, Map parametros)

Você tem um método para sua classe conhecer, mais três constantes. Isso é tão diferente de ter vários métodos assim?

A classe que for chamar o DAO aidna vai precisar saber qual tipo de busca será feita.

Você teria vários métodos, mas a lógica de montar um objeto baseado em registro, paginar, etc. pode ser reaproveitada por todos.

Não defendo um nem outro (acho os dois ruins, na verdade :P) mas qual o real benefício?

Shoes

Mauricio_Linhares

Sei lá, a minha luta é pra não definir um milhão de DAOs e métodos que vão fazer a mesma coisa.

Mas como você acha que isso poderia ser feito Phillip?

pcalcado

Não sei, por isso uso DAOs :frowning:

Mauricio_Linhares

Ta aí, mas de todo jeito esse uso de “identificadores” como você colocou no método é uma boa, fica melhor do que simplesmente passar o nome da query ou criar algumas dúzias de métodos pra fazer praticamente a mesma coisa. Vou ver o que eu consigo fazer aqui com enums pra botar isso na prática.

_fs

Cara, essa dúzia de métodos farão a mesma coisa por causa da implementação de acesso a dados que está utilizando.

E se fosse criar um DAO que busca numa coleção Java? Tenho certeza que essa dúzia de métodos fariam coisas bem diferentes ao invés de simplesmente passar uma query. “Ah, mas só vou usar jdbc mesmo.” Ok então :wink:

Mauricio_Linhares

LIPE:
Cara, essa dúzia de métodos farão a mesma coisa por causa da implementação de acesso a dados que está utilizando.

E se fosse criar um DAO que busca numa coleção Java? Tenho certeza que essa dúzia de métodos fariam coisas bem diferentes ao invés de simplesmente passar uma query. “Ah, mas só vou usar jdbc mesmo.” Ok então ;)

Pois é LIPE, no início eu tava até pensando sobre isso, “E se eu mudar pra um banco OO” ou “E se eu mudar pra um banco em XML”, mas eu to trabalhando com o Db4o (um banco OO pra Java e .Net) num trabalho aqui da faculdade (usando C#) e espero não ter que mexer com isso denovo nem tão cedo, é muito complicado de se trabalhar!

Acho que os bancos relacionais vão continuar por aí ainda por um boooom tempo :mrgreen:

_fs

Claro que sim. E também há várias maneiras e frameworks para acessar um banco de dados relacional.

Mas o problema não é esse, concordo com você em se ater ao necessário por hora. O lance do cliente precisar entender da implementação que acho problemático. Se você mudar de idéia e não querer mais o usar as queries, terá que alterar TODOS os clientes das classes, e não só o objeto que acessa os dados. E isso é algo a se temer.

J

Vi em um lugar uma dica interessante sobre criar Objetos de seleção:

public class FuncionarioSelecao {
   public void setRegistroIniciall(int registroInicial) {}
   public void filtrarPorCodigo(int codigo) {}
   public void filtrarPorNome(String nome) {}
   public void filtrarPorEndereco(String endereco) {}
}

public class FuncionarioDAO {
   public void salvar(Funcionario funcionario) {}
   public List consultar(FuncionarioSelecao selecao) {}
}

FuncionarioSelecao fs = new FuncionarioSelecao();
fs.filtrarPorNome("Maria");
Lista listaFuncionarios  = FuncionarioDAO.consultar(fs);
jack_ganzha
jprogrammer:
Vi em um lugar uma dica interessante sobre criar Objetos de seleção:
public class FuncionarioSelecao {
   public void setRegistroIniciall(int registroInicial) {}
   public void filtrarPorCodigo(int codigo) {}
   public void filtrarPorNome(String nome) {}
   public void filtrarPorEndereco(String endereco) {}
}
Essa classe FuncionarioSelecao parece apenas transferir o local onde os vários metodos para consulta estão. Quando houver um número muito grande de parametros buscáveis, vai haver uma série de filtrar*? Se for assim, qual a real vantagem disso sobre criar métodos especificos?

valeuz...

J

Na verdade essa classe irá conter os métodos associados com os atributos “buscáveis” da classe, ou seja, os parametros que podem ser usados em várias consultas diferentes. Isso traz uma maior reaproveitamento.
ex:

FuncionarioSelecao fs = new FuncionarioSelecao();
fs.filtrarPorCidade("São Paulo");
fs.filtrarPorIdadeMaiorQue(12);
fs.setTotalRegistros(10);
fs.setRegistraoInicial(10);

FuncionarioDAO.consultarFuncionariosEmDestaque(fs,Mes.JANEIRO);

Esse método irá trazer os funcionarios em destaque do mês de Janeiro (regra especifica do método) da cidade de são paulo e idade maior que 12.
Isso com paginação de 10 registros a partir do 10 registro.

Mauricio_Linhares

É exatamente esse tipo de coisa que eu quero evitar, milhares de classes e métodos pra fazer o mesmo serviço…

Se o framework de persistência dá essa possibilidade, porque não usar? Regra do mínimo de funcionalidade comum? Alguém aí falou de AWT?

Sei lá, as vezes é tanta “independência” disso ou daquilo que agente acaba sem “liberdade”.

maikonaraujo

Outra alternativa para diminuir a quantidade de métodos do Dao é deixar apenas métodos simples CRUD e findAll() , por exemplo, e buscas por Nome, endereço ou coisas do tipo se tornarem regras de negócio (processamento feito sobre os objetos) .
Óbvio que isso se torna enviável se sua base de dados é imensa, ai eu acho que não tem muito como escapar, por questão de performance o mais fácil eh implementar várias consultas diferentes.

maikonaraujo

Correção: inviável… hehehe

J

EDITADO:
Para usar hql nas regras de negócio é melhor usar SQL.

Isso não é ter métodos que fazem a mesma, coisa, pelo contrário, vc centraliza em uma lugar as operações comuns.
Acho engraçado o pessoal querer programar orientado e objetos e ficar com receio de criar classes para responsabilidades diferentes.
O meu único receio é criar métodos com muitos parêmêtros.
ex:

funcionario.consultar(cidade, idade, sexo, salario, departamento, ordenarPorNome, ordenarPorIdade, totalRegistros, registroInicial);

Esse é meu medo.

maikonaraujo

Um modo de solucionar isto é fazer sql dinâmico, passando apenas o Objeto como parâmetro e na cláusula WHERE vc vai filtrando onde cada atributo do objeto não é null.

sql += " WHERE 1 =1  " 

if ( obj.getNome != null )
   sql += " and nome = '" + obj.getNome + "'";

.....
Mauricio_Linhares

jprogrammer:
‘Mauricio Linhares’:

exatamente esse tipo de coisa que eu quero evitar, milhares de classes e métodos pra fazer o mesmo serviço…

EDITADO:
Para usar hql nas regras de negócio é melhor usar SQL.

Isso não é ter métodos que fazem a mesma, coisa, pelo contrário, vc centraliza em uma lugar as operações comuns.
Acho engraçado o pessoal querer programar orientado e objetos e ficar com receio de criar classes para responsabilidades diferentes.
O meu único receio é criar métodos com muitos parêmêtros.
ex:

funcionario.consultar(cidade, idade, sexo, salario, departamento, ordenarPorNome, ordenarPorIdade, totalRegistros, registroInicial);

Esse é meu medo.

Não tem HQL no código, na verdade, não tem nem banco de dados no código, é apenas uma string, do tipo “buscarCursosPorNome” e um Map com os parâmetros que essa busca pode receber.

Nesse caso, poderia não ser o mesmo serviço, se a persistência não fosse feita com o Hibernate, mas usando ele o código vai ser igual em todas as buscas. Vai ser sempre a execução de uma busca pelo nome que ela foi definida no arquivo de mapeamento com os parâmetros necessários.

maikonaraujo:
Outra alternativa para diminuir a quantidade de métodos do Dao é deixar apenas métodos simples CRUD e findAll() , por exemplo, e buscas por Nome, endereço ou coisas do tipo se tornarem regras de negócio (processamento feito sobre os objetos) .
Óbvio que isso se torna enviável se sua base de dados é imensa, ai eu acho que não tem muito como escapar, por questão de performance o mais fácil eh implementar várias consultas diferentes.

Imagina eu carregando uma tabela inteira, com uns 10000 registros, pra memória e mandar fazer uma ordenação nela, de objeto em objeto. Eu ia derrubar o servidor no primeiro select! A performance já era mesmo…

J

Já vi vários exemplos onde é passado o objeto para o método de pesquisa.
Na prática seria uma solução bem legal, mas deixa a arquitetura um pouco estranha.
ex:

funcionario f = new Funcionario();
f.setNome("Maria");
f.setIdade(18);

funcionario.consultar(f);

Melhor que passar o objeto é passar um objeto de seleção. onde voce determina em design time quais campos vc pode usar como filtro

funcionario fs = new FuncionarioSelecao();
fs.filtrarPorNome("Maria");
fs.filtrarPorIdade(18);
fs.ordenarPorNome(ASCENDENTE);
fs.ordenarPorIdade(ASCENDENTE);
funcionario.consultar(fs);

Dentro da classe vc vai montando o SQL (ou HQL) dinamicamente ou pega de um XML, ou de um properties, ou qualquer coisa.

Mauricio_Linhares
maikonaraujo:
O meu único receio é criar métodos com muitos parêmêtros.

Um modo de solucionar isto é fazer sql dinâmico, passando apenas o Objeto como parâmetro e na cláusula WHERE vc vai filtrando onde cada atributo do objeto não é null.

sql += " WHERE 1 =1  " 

if ( obj.getNome != null )
   sql += " and nome = '" + obj.getNome + "'";

.....

Ave maria!

Faça isso não pelo amor de deus!

Usa busca por exemplos ou então a Criteria API. SQL on-the-fly só dá dor de cabeça.

Mauricio_Linhares

jprogrammer:
Já vi vários exemplos onde é passado o objeto para o método de pesquisa.
Na prática seria uma solução bem legal, mas deixa a arquitetura um pouco estranha.
ex:

funcionario f = new Funcionario();
f.setNome("Maria");
f.setIdade(18);

funcionario.consultar(f);

O Hibernate já faz isso também, é até uma coisa que já estaria definida no DAO base, que eu citei lá na primeira mensagem.

maikonaraujo

Maurício Linhares:

Se o framework de persistência dá essa possibilidade, porque não usar?
Sei lá, as vezes é tanta “independência” disso ou daquilo que agente acaba sem “liberdade”.

Concordo, existe aquele momento em que temos que ser pragmáticos e ter consiência que estamos desenvolvendo uma aplicação que possui suas regras de negócio particulares e não um framework mais genérico do mundo. Ou seja, acaba que o Dao fica com muitos métodos mesmo.

Se correr o bicho pega se ficar o bicho come… :lol: :lol:

Mauricio_Linhares

maikonaraujo:
Maurício Linhares:

Se o framework de persistência dá essa possibilidade, porque não usar?
Sei lá, as vezes é tanta “independência” disso ou daquilo que agente acaba sem “liberdade”.

Concordo, existe aquele momento em que temos que ser pragmáticos e ter consiência que estamos desenvolvendo uma aplicação que possui suas regras de negócio particulares e não um framework mais genérico do mundo. Ou seja, acaba que o Dao fica com muitos métodos mesmo.

Se correr o bicho pega se ficar o bicho come… :lol: :lol:

Agora que eu comecei a ler o “J2EE Development Without EJB” é que eu fiquei com a pulga atrás da orelha.

Portabilidade entre frameworks de mapeamento objeto/relacional também vai ser um phantom requirement? :shock:

Pelo menos pelo que eu to vendo, eu não vou trocar o Hibernate por outra coisa nem tão cedo…

J

Na minha humilde opinião não é a questão de trocar, mas de clareza de código também e divisão de responsabilidades.
Vamos supor que vc tenha que no futuro implemntar um mecanismo de log toda vez que fizer uma inserção.
Separando as responsabilidades isso fica mais fácil de implementar.

Não dá para prever tudo (impossível). Mas tente prever pelo menos aquilo que sua experiência já lhe mostrou.
Os patterns foram feitos para serem usados, pois é o resultado da solução de problemas que foram enfrentados anteriormente por alguém.
Mesma coisa os frameworks.
Mas devem ser usados com coerencia e não por modismos.
Acho que desenvolver sua apliação para se moldar ao pattern é errado.
Mas usar sua apliação para usar o pattern é o correto.

maikonaraujo

jprogrammer:
Na minha humilde opinião não é a questão de trocar, mas de clareza de código também e divisão de responsabilidades.

Separando as responsabilidades isso fica mais fácil de implementar.


Os patterns foram feitos para serem usados, pois é o resultado da solução de problemas que foram enfrentados anteriormente por alguém.
Mesma coisa os frameworks.
Mas devem ser usados com coerencia e não por modismos.
Acho que desenvolver sua apliação para se moldar ao pattern é errado.
Mas usar sua apliação para usar o pattern é o correto.

Foi isto mesmo que eu quis dizer, concorodo que uma arquitertura bem dividida em camadas eh uma ótima solução. Mas sobrecarregar cada camada com patterns pode ser perigoso, tanto em tempo de desenvolvimento quanto para a simplicidade do código. Faz-se o simples implementando os patterns (SEMPRE QUE NECESSÁRIO), e o resto é específico da sua aplicação, se houver necessidade de uma mudança muito brusca vc pode refatorar o código e adcionar mais patterns se necessário.

maikonaraujo

O Dao, na minha opnião, tem como uma de suas funções separar (arquitetura em camadas) a parte de acesso a sua base de dados do restante da sua aplicação.

Mauricio_Linhares

Tá aí um exemplo que eu não tinha pensado.

Imagina um monte de DAOs cheios de métodos de busca, todos com parâmetros diferentes, executando buscas diferentes, cada métodozinho ia ter que ter um logger implementado só pra ele! Olha a bagaceira de código que ia ter que ser escrita só pra logar isso!

Se for com um único método, o executar(String nomeDaQuery, Map parametros) eu só vou escrever o log uma única vez e vou ter tanto o nome da query que foi executada como todos os parâmetros que foram passados, todos reunidos em um só lugar :mrgreen:

E realmente não dá pra pensar muito não, porque os métodos de pesquisa estão retornando Lists, quem garante que outro framework qualquer vai retornar Lists também? E eu já matei acesso direto ao banco, porque o driver do banco nunca vai retornar um List né, vou ter que usar mapeamento objeto/relacional de qualquer jeito. E agora, como ficar independente da camada de persistência? É realmente possível fazer isso?

Acho que eu vou é simplificar mesmo a coisa, criar novos métodos pra fazer buscas, só se for pra montar uma busca em tempo de execução ou se houver necessidade de usar coisas específicas de algum banco.

Vou fazer um novo movimento agora:

“Diga não aos milhares de DAOs e os seus milhares de métodos! Os seus dedos agradecem!”

J

É verdade Maurício, generalizar nesses casos é bem melhor.
Estou entendendo agora a sua posição.
Mas uma coisa muito gernérica não tira a flexibilidade e os recursos type safe do java ?
ex:

class DAO {
  public void salvar(Object object) {
  }
}

class FuncionarioDAO extends DAO {
  public void salvar(Object object) {
  }
}

Funcionario f = new Funcionario();
Departamento d = new Departamento();

FuncionarioDAO.salvar(d);
FuncionarioDAO.salvar(f);

Perco a checagem em tempo de compilação.

EDITADO:

Enquanto o List vai ai mais uma classe: De Colecao.

class FuncionarioColecao {
  public boolean proximo() {};
  public Funcionario getFuncionario() {}
}

FunconarioColecao fc = Funcionario.consultar();
while (fc.proximo()) {
  Funcionario  f = fc.getFuncionario();
}

Idependencoia total

Mauricio_Linhares

Isso é uma coisa simples de fazer.

No meu sistema aqui, o DAO só insere objetos que implementem a interface “Persistivel”, que é uma interface de marcação (que nessa implementação com o Hibernate ganhou um identificador via aspectos, mas isso já é outra história). Usando uma interface de marcação esse problema ia ser resolvido fácil, porque o Hibernate “descobre” qual a classe que está sendo persistida dando um getClass() nela e enviando ela pro “persister” adequado. Assim o teste de tipos em tempo de compilação pros métodos de inserir, atualizar e deletar estaria resolvido.

Mas você tocou num ponto interessante, dos “objetos” a coisa tá resolvida, mas das coleções ainda não, vou dar uma estudada em generics pra ver como isso pode vir a funcionar.

cv1

Impressionante como a gente se frita quando qualquer discussao sobre DAOs aparece aqui no GUJ. Eu vou ser o primeiro a admitir que eu adoro ficar pensando nisso, mas sinceramente, eu tenho mais o que fazer do que ficar pensando na Arquitetura do DAO Generico Que Resolvera Todos Os Problemas De Persistencia Da Humanidade ™. Se tal coisa existisse ou pudesse de fato ser inventada, nos ja estariamos usando faz tempo - nos nao somos os unicos a esquentar a cabeca com isso.

De agora em diante, eu vou usar uma resposta padrao pra esses topicos:

1 - Use o que o seu framework de persistencia te oferece - voce nao vai trocar de framework, e se for, a arquitetura do seu sistema vai ter que mudar de qualquer jeito.

2 - Use um bom cache ou aprenda a usar o cache do seu framework, e caso ele nao seja completamente transparente, aprenda a controla-lo bem

3 - Nao perca mais do que 30 minutos decidindo qual vai ser a hierarquia de classes dos seus DAOs e, se alguma coisa tao estranha assim que o minimo do bom-senso gasto durante aqueles 30 minutos aparecer, um refactoring conserta.

4 - Nenhum refactoring eh tao grande assim se voce tiver testes unitarios e funcionais pra te ajudar.

5 - Faca o mais simples, mas nao o simplorio, e so reclame de performance se voce tiver provas concretas na mao.

6 - Se possivel, use objetos, com dados e comportamento, nao tabelas com farofa em cima.

7 - Mantenha a informacao perto de onde ela vai ser usada.

8 - Use as interfaces ja disponiveis na API do Java e do seu framework para fazer as coisas a que se destinam (Serializable, Externalizable, Criteria), e nao as reinvente ou abstraia.

9 - Nao, persistencia nunca vai ser transparente.

10 - Nao, o Prevayler, Space4J ou outros mecanismos de command-logging nao sao a solucao que estamos discutindo, e provavelmente nao sao solucoes de longo prazo para nenhum sistema de grande porte que vai ser mantido em mais de um lugar.

J

Com o genérics: beleza.
Mas com o 1.4 criar uma interface de colecao seria interessante.

Mauricio_Linhares

5 estrelas CV

Mas matou a discussão :lol:

J

É verdade, na prática mesmo tudo isso é o que vale.
Depois dessa até eu desisto…

cv1

jprogrammer:
Com o genérics: beleza.
Mas com o 1.4 criar uma interface de colecao seria interessante.

Nao, nao seria. Leia o ponto 8.

Kleber_Santos

fritei o cerebro com tudo isso…
hehheheh
:-o :mrgreen: :-o :mrgreen:

Mauricio_Linhares

Kleber Santos:
fritei o cerebro com tudo isso…
hehheheh
:-o :mrgreen: :-o :mrgreen:

Normal, o GUJ faz isso com agente :mrgreen:

Kleber_Santos

verdade Marcelo…

mas no fundo, no fundo mesmo amigão

Amuuuu fritar o cerebro

:mrgreen: :mrgreen: :mrgreen:

Diogenes

Eu héin?! :roll:

Mauricio_Linhares

Kleber Santos:
verdade Marcelo…

mas no fundo, no fundo mesmo amigão

Amuuuu fritar o cerebro

:mrgreen: :mrgreen: :mrgreen:

Marcelo :?:

F

Olá,

O impressionante dessas discucoes, fora tudo que o CV ja falou, é que tudo que é levantado é implementado pelo Hibernate.
Tem respostas que leio e fico pensando, será que ele ta falando isso e nunca olhou o Hibernate.

Eu sei que ele nao é perfeito, mas até agora nao conheco nada melhor para o que ele se dispoe. Abstrair bases de dados e mapeamento O/R.

Esse tipo de frase o CV deve pensar na hora que ta bebendo “in london”, nao é possivel.

:mrgreen:

]['s

Mauricio_Linhares

fabgp2001:

Esse tipo de frase o CV deve pensar na hora que ta bebendo “in london”, nao é possivel.

:mrgreen:

]['s

Como assim, “não é possível”?

pcalcado

Fabio, apesar de concordar com o carlos ainda nao entendi como o Hibernate eliminaria DAOs, varios metodos de pesquisa, etc. Pdoeria dar um exemplo?

Shoes

J

Eu acho que colocar o hibernate em uma camada abaixo dos DAOs não é problema nenhum.
Achei bem legal os itens que o CV colocou, pois na prática temos que simplificar mesmo.
Mas abstrair é bom para ter reuso de código e facilitar implementações futuras. Fazer rafactory sempre dá trabalho, então tentar ter uma arquitetura que facilita de uma forma cada vez maior novas implementações e o reuso.
É lógico que como o CV falou: Ficar mais de 30 minutos para decidir em projeto a arquitetura de uma DAO é inviável.
Mas como estamos no GUJ é sempre bom discutir, é para isso que ele existe.

_fs

Insisto no ponto de abstrair o Hibernate pois, mesmo usando-o, há várias formas de realizar uma mesma tarefa. Exemplo simples são as interfaces Query e Criteria.

J

É verdade LIPE, até para migração de versão de uma hibernate para outro. E manter uma padrão entre os desenvolvedores do projeto.

cv1

Hmm… discordo, Lipe. Quanto tempo demora pra mudar o codigo caso vc perceba que usar a Query API nao foi uma boa ideia pq agora vc tem um novo requisito doente que precisa da Criteria API de qualquer jeito?

E, mesmo assim, fica tao feio usar as duas APIs ao mesmo tempo? Ta tudo no Hibernate, afinal…

Mauricio_Linhares

cv:
Hmm… discordo, Lipe. Quanto tempo demora pra mudar o codigo caso vc perceba que usar a Query API nao foi uma boa ideia pq agora vc tem um novo requisito doente que precisa da Criteria API de qualquer jeito?

E, mesmo assim, fica tao feio usar as duas APIs ao mesmo tempo? Ta tudo no Hibernate, afinal…

Pois é, pra fazer uma pesquisa que já está definida, usa uma named query mesmo, lá no mapeamento, pra montar uma query em tempo de execução, usa criteria, que facilita e ainda facilita ainda mais pra trocar de banco de dados.

_fs

cv, não é uma questão de tempo. Como disse, o problema está em mudar o código do cliente.
As classes que chamam métodos na camada persistência não deveriam se preocupar como diabos está programado para devolver uma lista de pessoas ao fazer camadaDePersistencia.pessoasByAge( int age ).

F

pcalcado:
Fabio, apesar de concordar com o carlos ainda nao entendi como o Hibernate eliminaria DAOs, varios metodos de pesquisa, etc. Pdoeria dar um exemplo?

Shoes

Shoes,

Desculpa a demora em respodner, mas vamos a minha opiniao.

O que eu preciso em uma classe de persistencia para uma classe de negocio?
Metodos que facam o CRUD e metodos de pesquisa que sao expecificos para cada Entidade.
Entao os metodos Save, Update (ou um unico SaveOrUpdate) e um Delete sao iguais para todas entidades. Aqui acho que todas entidades podem usar a mesma classe para essas operacoes. Os metodo find, findAll, ect (cada um nomeia de um jeito) só diferem no criterio de busca, ou seja, se tu tem classes de Query e/ou Criteria tu nao precisa ficar criando classes distintas para tratar isso tb é so tem um um metodo find recebendo o criterio de busca e pronto.
Pensando assim, pq eu preciso fazer um DAO para cada classe duplicando metodos? É nesse ponto que eu digo que o hibernate implementa e facilita. Ja vi varias discucoes aqui sobre DAO’s e a discucao corria sempre no mesmo assunto, fazer classe expecifica, ou classe generica, como fazer as consultas, etc. Eu nao acho que tratar assim, os metodos basicos em uma unica classe seja generalizar, a meu ver é simplificar, nao duplicando codigo e ficando somente a parte de consulta (Query e Criteria) como parte expecifica para cada entidade e essa sim voce tera que separar, aqui eu ja trabalhei com ValeuListHandle principalmente quando preciso paginar o retorno, aqui tb utilizo as facilidades do Hibernate para isso.
Desse modo só funciona se eu usar algum framework O/R que me provenha estas facilidades, se eu for partir para fzar tudo na mao provavelmente nao conseguirei fazer desse modo, provaevelmente terei que criar classes expecificas para cada entidade ou reiventar a roda escrevendo um novo framework O/R que atenda as minhas necessidades, mas ai será que vale a pena? E é nesse ponto que eu digo que o Hibernate implementa tudo, ele nao é perfeito mas fora situacoes especificas o resto ele comtempla.

Fora isso tem a parte que o CV comentou, cache, transacao, api de consulta, sistema para paginação, etc tudo sao providos pelo Hibernate.

O que voce acha?

]['s

F

LIPE:
cv, não é uma questão de tempo. Como disse, o problema está em mudar o código do cliente.
As classes que chamam métodos na camada persistência não deveriam se preocupar como diabos está programado para devolver uma lista de pessoas ao fazer camadaDePersistencia.pessoasByAge( int age ).

Eu concordo com o LIPE quando se trata de um produto, muitas vezes o produto fica em uso por anos e é sempre bom ter uma facilidade para mudancas na parte de infra do sistema sem ter que mexer no core da aplicacao.

]['s

Mauricio_Linhares

Se independência de ferramenta de mapeamento O/R for uma necessidade do sistema, vale a pena ter esse trabalho todo. Se não for, pra que se preocupar com isso?

O overengineering anda solto na comunidade Java :mrgreen:

pcalcado

Êpa…

Não falei em não usar Hibernate, IBatis ou Zahl-OR (e acho que esse não era o foco). DAOs não te impedem disso :wink:

Então, acho que pelo que entendi você está propondo usar uma classe genérica ao invés de ter um DAO para cada entidade. Isso diminuiria a quantidade de classes mas não a quantidade de métodos de consulta.

De qualquer modo a princípio você pode reutilizar o mesmo DAO aproveitando a idéia original do Maurício com Specification pattern.

Eu pessoalmente acho que um Repositório para cada entidade tem mais valor no domínio.

Shoes

Mauricio_Linhares

Você já tinha falado nessa história de repositório antes Phillip, como é que é isso?

F

pcalcado:
Êpa…

Não falei em não usar Hibernate, IBatis ou Zahl-OR (e acho que esse não era o foco). DAOs não te impedem disso ;)

Concordo e nem eu falei que nao precisa usar, só comentei que muita coisa do que era discutido ja é implementado pelo Hibernate (ou outro framework O/R decente). Por isso prefiro perder mais tempo discutindo assuntos que vao agregar mais valor.

Nao que eu estaja propondo uma classe generica, mas se meu save é igual para todas classes, pq irei escrever mais de um? :wink:

pcalcado:

De qualquer modo a princípio você pode reutilizar o mesmo DAO aproveitando a idéia original do Maurício com Specification pattern.
Eu pessoalmente acho que um Repositório para cada entidade tem mais valor no domínio.

Vou da uma olhada nisso, mas ultimamente tenho usado (ou tentando usar) o ActiveRecord.

pcalcado

Bom, eu tenho um pé atrás com AR, mas tudo bem :stuck_out_tongue:

De qualquer modo, onde você faz consultas?

Um repositório é um lugar onde você armazena entidades. Quando você rpecisa armazenar um objeto e não tem um lugar lógico no seu domínio para isso, você usaria um repositório.

É quase um DAO, mas utilizado direamente no seu domínio, está na mesma camada. Ele age como um agregado de objetos de um mesmo tipo, pro domínio não existe persistência, é como se fosse uma Collection especializada.

Se um Repositorio de Usuarios receber uma consulta:

public List listBySpec(Specification s)

Você poderia colcoar seus critérios dentro da implementação de Specification e ter apenas um método para qualquer consulta. Por aí que estou pensando…

F

pcalcado:
Bom, eu tenho um pé atrás com AR, mas tudo bem :stuck_out_tongue:

Sempre é bom ter um pé atras, mas tb nao é por isso que nao vou experimentar. Até agora nao tive problemas e to até gostando, mas um dos pé continua atras. :stuck_out_tongue:

pcalcado:

De qualquer modo, onde você faz consultas?

No meu objeto de negocio ué. :smiley:

public class User() { ... public List<User> getUserByAge(int age) { } ...

E o SQL ou melhor HQL normalmente tenho usado named query.

Agora se eu preciso algo mais trabalhado ou consultas mais complicadas eu gosto de usar um ValueListHandle.

]['s

pcalcado

Eu não consigo entender isso. A mistura de responsabilidades entre negócio e consulta tem que estar nesse objeto?

O que você faz assim é pegar uma série de responsabilidades e agrupar numa classe que já tem as suas próprias responsabilidades.

A classe em si fica com coesão baxíssima, se acopla à tecnologia de persistência e não é tão diferente de ter uma classe que faça o mapeamento em separado, é a mesma coisa em um lugar diferente (e impróprio IMHO).

Qual a real vantagem de fazer isso? :roll:

F

pcalcado:
Eu não consigo entender isso. A mistura de responsabilidades entre negócio e consulta tem que estar nesse objeto?

O que você faz assim é pegar uma série de responsabilidades e agrupar numa classe que já tem as suas próprias responsabilidades.

A classe em si fica com coesão baxíssima, se acopla à tecnologia de persistência e não é tão diferente de ter uma classe que faça o mapeamento em separado, é a mesma coisa em um lugar diferente (e impróprio IMHO).

Qual a real vantagem de fazer isso? :roll:

No meu caso, que estou usando AR a parte de consulta em si nao esta no meu objeto de negocio. Uso composicao pra fazer isso. Atualmente to usandoa implementacao que o CV postou por aqui em outro topico, adaptado a arquitetura que eu ja havia montado no meu sistema. A unica coisa que meu objeto User (do exemplo) sabe é buscar a idade, mas ele nao sabe de onde vem nem como se faz pra buscar de la.

Eu nao entendi a tua frase:

Se o que tu chama de consulta é a “arte” de buscar efetivamente os dados do banco realmente nao há essa mistura visto que meu objeto de negocio nao faz a busca propriamente.

Ps.: Acho que o assunto do topico ja desvirtuo denovo. E essa parte do AR nao tem nada a ver com meu comentários dos DAO feitos anteriormente. :stuck_out_tongue:

]['s

cv1

Posso fazer soh um comentario rapidinho? Metodos como List getUsersByAge(int age) nao sao uma boa: eh bem melhor ter um List findUsers(User example) que lida com qualquer parametro necessario (usando Hibernate, isso eh bem trivial de implementar) :slight_smile:

F

Hm, verdade. Nao tinha pensado nisso ainda.

Agora CV oque tu acha de tudo que ta sendo falado por aqui? Ja que tu é um que gosta de AR.

Da tua opiniao ai. :mrgreen:

]['s

Thiago_Senna

Olá!

Essa discussão não é muito pro meu bico, mas eu gostei de uma solução que é a seguinte: Peguei essa idéia na aplicação PetSoar, do livro Java Open Source Programming!

Tenho uma interface PersistenceManager, uma classe que implementa a PersistenceManager, e um componenete que faz uma espècie de integração entre meu objeto de negócio e o Persistence Manager.... .. vou postar o código, e vejam o que acham... Talvez não ajude em nada, mas é uma maneira q achei interessante de lidar com a persistência!

public interface PersistenceManager {
	
	/**
	 * Save any object of domain in the database
	 * 
	 * @param obj
	 */
	public void save(Object obj);
	/**
	 * Remove any objet of domain from the database
	 * 
	 * @param obj
	 */
	public void remove(Object obj);
	/**
	 * Retrie a objet of domain from the database by id
	 * 
	 * @param id
	 * @return UserStorie Object
	 */
	public Object load(Long id);
	/**
	 * Retrieve all objects of a specific object domain.
	 * 
	 * @param c Class of the object domain
	 * @return a collection of objects
	 */
	public List findAll(Class c);

}
public class HibernatePersistenceManager implements PersistenceManager {
	
	Log log = LogFactory.getLog(HibernatePersistenceManager.class);

	/* (non-Javadoc)
	 * @see net.java.dev.xpturbine.persistence.PersistenceManager#save(java.lang.Object)
	 */
	public void save(Object obj) {
		try {
			Session session = HibernateUtil.getSession();
			session.saveOrUpdate(obj);
		} catch (HibernateException e) {
			log.error(e.getMessage(), e);
			throw new PersistenceException(e.getMessage(), e);
		}
	}

	/* (non-Javadoc)
	 * @see net.java.dev.xpturbine.persistence.PersistenceManager#remove(java.lang.Object)
	 */
	public void remove(Object obj) {
		try {
			Session session = HibernateUtil.getSession();
			session.delete(obj);
		} catch (HibernateException e) {
			log.error(e.getMessage(), e);
			throw new PersistenceException(e.getMessage(), e);
		}

	}

	/* (non-Javadoc)
	 * @see net.java.dev.xpturbine.persistence.PersistenceManager#load(java.lang.Long)
	 */
	public Object load(Long id) {
		Object obj;
		try {
			Session session = HibernateUtil.getSession();
			obj = session.load(UserStorie.class, id);
		} catch (HibernateException e) {
			log.error(e.getMessage(), e);
			throw new PersistenceException(e.getMessage(), e);
		}
		return obj;
	}

	/* (non-Javadoc)
	 * @see net.java.dev.xpturbine.persistence.PersistenceManager#findAll(java.lang.Class)
	 */
	public List findAll(Class cls) {
		List list = Collections.EMPTY_LIST;
		
		try {
			Session session = HibernateUtil.getSession();
			list = session.find("FROM userStorie IN CLASS " + cls.getName());
		} catch (HibernateException e) {
			log.error(e.getMessage(), e);
			throw new PersistenceException(e.getMessage(), e);
		}
		
		return list;
	}

}
public class ReleaseManager {
	
	private PersistenceManager persistenceManager;
	
	/**
	 * Set a persistence manager.
	 * 
	 * @param persistenceManager The persistenceManager to set.
	 */
	public void setPersistenceManager(PersistenceManager persistenceManager) {
		this.persistenceManager = persistenceManager;
	}
	
	/**
	 * Save a user storie in the database.
	 * 
	 * @param userStorie
	 */
	public void saveUserStorie(UserStorie userStorie) {
		persistenceManager.save(userStorie);
	}
	/**
	 * Remove a user storie from the database
	 * 
	 * @param userStorie
	 */
	public void removeUserStorie(UserStorie userStorie) {
		persistenceManager.remove(userStorie);
	}
	/**
	 * Retrieve a user storie by id from the database
	 * 
	 * @param id UserStorie ident
	 * @return a retrieved UserStorie
	 */
	public UserStorie loadUserStorie(long id) {
		Object storie = persistenceManager.load(new Long(id));
		return (UserStorie) storie;
	}
	/**
	 * Retrievel all user stories from the database
	 * 
	 * @return list of user stories
	 */
	public List findAllUserStories() {
		List userStories = persistenceManager.findAll(UserStorie.class);
		return userStories;
	}
}

Ainda tem alguns errinhos e melhorias para ser feitas. Por enquanto o componente só persiste a classe UserStorie, mas em breve terei outras classes, e para cada uma delas irei acrescentando métodos para tratar dessas responsabilidades, mas enquanto isso, a classe HibernatePersistenceManager irá crescer pouco, e se manterá simples e fácil de entender!!!

Abraços!
Thiago Senna

J

Não sou puxa-saco.
Cara eu acho que vc tem bagagem até de sobra para postar nesse tópico.

É lógico que tem especialistas como o Shoes e Cv em arquitetura mas sua ppinião é bem interessante.

Mauricio_Linhares

Não entendi, ele dá um load passando só um “Long”, mas dá um findAll passando a “classe”.

Ou ele faz de um jeito ou faz de outro, não acho que se deva misturar tudo assim não. Bota a classe sendo passada no load também ou então tira a classe do findAll.

Thiago_Senna

Maurício Linhares:
Não entendi, ele dá um load passando só um “Long”, mas dá um findAll passando a “classe”.

Ou ele faz de um jeito ou faz de outro, não acho que se deva misturar tudo assim não. Bota a classe sendo passada no load também ou então tira a classe do findAll.

Olá Maurício!

Esta parte esta realmente precisando de uma melhoria. Eu vou adicionando estas melhorias de acordo vou precisando delas.

No caso do meu objeto UserStorie, sua identificação é um atributo do tipo Long!

Em breve criarei outro objeto que se chamará Release, e depois outros e mais outros, Quando um deles for algum outro tipo de identificação, dai eu uso

public Obect load(Object obj);

Em suma, essa parte realmente precisaria de uma melhoria, mas eu naum a fiz por que naum precisei ainda! :wink:

Abraços!
Thiago Senna

F

Thiago Senna:
Em breve criarei outro objeto que se chamará Release, e depois outros e mais outros, Quando um deles for algum outro tipo de identificação, dai eu uso

public Obect load(Object obj);

Thiago,

Tenta usar Serializable ao inves de Long ou Object. A meu ver fica melhor.

public Obect load(Serializable id);

]['s

Thiago_Senna

Fábio,

essa eu não imaginava! :smiley: Deixa comigo, vou usar Serializable então!!! :wink:

Abraços!
Thiago

louds

Query by example só tem um porêm, todos atributos da tua tua classe tem que possuir um valor inválido, normalmente null, e ser possivel ter somente alguns valores atribuidos. QBE, até onde eu ví, normalmente leva a você ter um punhado de java beans/VOs e não domain objects.

rodrigo_corinthians

Achei essa discussão muitooooo interessante e resolvi criar uma classe genérica(com apenas ações CRUD) para os meus Dao’s e obtive resultados significativos em relação a reutilização, irei mostrar o código se algo pode ser implementado favor me avisem.

public interface IGenericPersistenceDao extends Serializable {
    
    public void insert(IBean bean) throws SystemException;
    
    public void update(IBean bean) throws SystemException;
    
    public Object selectPrimaryKey(Integer pk) throws SystemException;
    
    public Collection select(IBean bean) throws SystemException;
    
    public void delete(IBean bean) throws SystemException;
    
}

// Minha classe genérica do Hibernate
public abstract class AbstractGenericPersistenceDao implements IGenericPersistenceDao {

    private IConexao hibernateDao;
    private Session session;
    
	public AbstractGenericPersistenceDao() throws SystemException {
        hibernateDao = Conexao.getInstance();
        session = (Session) hibernateDao.getConnection();
	}
	
	private boolean isBean(IBean bean) throws SystemException {
		if(getClassBean().getClass().getName().equalsIgnoreCase(bean.getClass().getName())){
			return true;
		}
		return false;
	}
	
	private void validationBean(IBean bean) throws SystemException {
    	if(!isBean(bean)){
    		throw new SystemException("Tipo de objeto Bean é inválido");
    	}
	}
	
	public void insert(IBean bean) throws SystemException {
        try {
       	    validationBean(bean);
            session.save(bean);
            session.flush();
        } catch(HibernateException hibernateException) {
            throw new SystemException(hibernateException);
        }
	}

	public void update(IBean bean) throws SystemException {
        try {
        	validationBean(bean);
            session.update(bean);
            session.flush();
        } catch(HibernateException hibernateException) {
            throw new SystemException(hibernateException);
        }
	}

	public Object selectPrimaryKey(Integer pk) throws SystemException {
        try {
        	validationBean(getClassBean());
        	Object object = null;
        	object = session.load(getClassBean().getClass(), pk);
            session.flush();
            return object;
        } catch(HibernateException hibernateException) {
            throw new SystemException(hibernateException);
        }
	}

	public Collection select(IBean bean) throws SystemException {
		try {
			validationBean(bean);
			String sqlString = "from "+bean.getClass().getName();
			List list = session.find(sqlString);
			Collection collection = new ArrayList(list);
			return collection;
		} catch(HibernateException he) {
			throw new SystemException(he);
		}
		
	}

	public void delete(IBean bean) throws SystemException {
        try {
        	validationBean(bean);
            session.delete(bean);
            session.flush();
        } catch(HibernateException hibernateException) {
            throw new SystemException(hibernateException);
        }
	}
	
	abstract protected IBean getClassBean() throws SystemException;
	
}

Agora os meus daos ficaram simplesmente assim. :smiley:

public class PessoaDaoNew extends AbstractGenericPersistenceDao {

	public PessoaDaoNew() throws SystemException {
		super();
	}

	protected IBean getClassBean() throws SystemException {
		return AbstractBeanFactory.createBean(PessoaBean.class);
	}

}


public class PessoaFisicaDaoNew extends AbstractGenericPersistenceDao {

	public PessoaFisicaDaoNew() throws SystemException {
		super();
	}

	protected IBean getClassBean() throws SystemException {
		return AbstractBeanFactory.createBean(PessoaFisicaBean.class);
	}

}


public class PessoaJuridicaDaoNew extends AbstractGenericPersistenceDao {

	public PessoaJuridicaDaoNew() throws SystemException {
		super();
	}

	protected IBean getClassBean() throws SystemException {
		return AbstractBeanFactory.createBean(PessoaJuridicaBean.class);
		
	}

}

Até ontem( :slight_smile: ) as minhas ações CRUD’s eram codificadas(ou replicadas?) dentro de cada Dao, agora preciso apenas abstrair um método que retorna o bean do Dao para manter a integridade dos daos, tipo pra não chamar um Dao N passando um bean M…

O problema será quando tiver uma consulta específica, estou pensando ainda em como implementar… :?

Fui…

Sem mais, Rodrigo.

fmeyer


heehhe

Mauricio_Linhares

Rodrigo, porque você não cria um único Dao, que faça todas as operações de CRUD, salvar, atualizar, listar e carregar pelo identificador (poderia até ter buscar por exemplos). Aí quando você precisar de uma busca específica, cria um DaoEntidade com essa busca, mas deixa os CRUD lá no CrudDao, ou seja lá o que ele for.

Essa validação que você esta fazendo é desnecessária, se o objeto não puder ser persistido pelo Hibernate, ele vai lançar uma exceção.

Eu não vi nenhuma transação sendo aberta e terminada no seu código, ele está fazendo alguma atualização no banco de dados? Ele está funcionando?

Evite usar o flush(), o Hibernate sabe quando ele deve enviar os dados pra uma tabela e só vai fazer isso quando for estritamente necessário, diminuindo o gasto com banda de rede.

cv1

Eu acho que eu ja disse o bastante aqui, ou faltou alguma coisa? :slight_smile:

rodrigo_corinthians

Maurício Linhares:
Rodrigo, porque você não cria um único Dao, que faça todas as operações de CRUD, salvar, atualizar, listar e carregar pelo identificador (poderia até ter buscar por exemplos). Aí quando você precisar de uma busca específica, cria um DaoEntidade com essa busca, mas deixa os CRUD lá no CrudDao, ou seja lá o que ele for.

Acho que não seria válido ter apenas um Dao q fizesse o CRUD de todas as tabelas, eu prefiro ter um Dao(desde que esse fique bem enxuto) pra cada tabela do jeito q está, por questão de arquitetura e tals.

Eu faço essa validação para ter certeza que no DaoUsuario(exemplo) estará sempre passando o BeanUsuario, assim ele nem chegará nessa exceção que o hibernate mandaria e creio que fica mais seguro a nível de programação.

Sim está fazendo o CRUD certinho, para controle de transação fiz uma classe que cria apenas uma única transação para todo(s) o(s) negócio(s), eu a chamo na ultima camada do sistema, exemplo

...
// Aqui poderia ser um Servlet, Swing...
    public static void main(String[] args) {

        ITransaction t = null;
        try {
            t = SimpleTransaction.getInstance();
            t.start();
            
	    // Aqui fica as classes de negócio e eles chamam os Dao's necessários.

	    t.commit();
        } catch(SystemException se) {
            t.rollback();
            se.printStackTrace();
        } finally {
            t.close();
    }
...

Com o código acima usa vários regras(e consequentemente vários daos) e se acontecer alguma exceção dou um rollback, estando tudo ok comito a transação ai ele salva no banco, por enquanto ainda não estou usando o JTA(fiz a classe de transação na unha mesmo).

Maurício Linhares:

Evite usar o flush(), o Hibernate sabe quando ele deve enviar os dados pra uma tabela e só vai fazer isso quando for estritamente necessário, diminuindo o gasto com banda de rede.

Blz valew pela dica. :wink:

Ah e sobre as consultas específicas pra cada entidade já resolvi o problema, implemento no Dao uma interface com os métodos a mais. heheh

Falow!

Sem mais, Rodrigo.

Mauricio_Linhares

Se você vai fazer um Dao Crud pra cada entidade, porque não faz a validação no próprio parâmetro?

public void salvar (Usuario usuario)

public Usuario carregar (Integer id)

Fica muito mais limpo e dá um bom motivo pra se ter vários Daos fazendo CRUD do mesmo jeito. Do jeito que você está fazendo tá só duplicando código.

rodrigo_corinthians
Maurício Linhares:
Se você vai fazer um Dao Crud pra cada entidade, porque não faz a validação no próprio parâmetro?
public void salvar (Usuario usuario)

public Usuario carregar (Integer id)

Fica muito mais limpo e dá um bom motivo pra se ter vários Daos fazendo CRUD do mesmo jeito. Do jeito que você está fazendo tá só duplicando código.


Não véio acho que vc não entedeu(ou eu não expliquei direito), criei um Dao pai(classe abstrata) onde ele provém as ações CRUD para os restantes dos Daos filhos, não estou duplicando(ou sobrepondo) os métodos nos filhos, apenas o método que retorna o bean do Dao para validar posteriormente.

Sem mais, Rodrigo.

C

Eu realmente gostei dessa idéia de daos genéricos com o hibernate.

Por um lado, mata um padrão, que é ter um dao para cada entidade, por outro, é mais inteligente e nao traz duplicacao de codigo!

E eu estava pensando um pouco (perdoem-me a inexperiencia): será que realmente é possível ter uma camada de persistencia totalmente flexivel, em que, apenas implementando novos daos eu consiga mudar a persistencia, sem ter que alterar as classes que usam os daos?

Pois, afinal, por exemplo, se eu quero uma consulta um pouquinho mais complexa, tenho que usar sql ou hql. Mas, e como faria as consultas complexas persistindo em arquivos binarios? E em xml´s? E em prevayler?

Enfim, o q acham?

Mauricio_Linhares

Rapaz, “totalmente” nunca iria ser possível, mas com os vários DAOs (um pra cada entidade) seria mais fácil. Só que ao mesmo tempo também seria mais trabalhoso.

Se isso for uma necessidade do sistema (possibilidade de transitar entre vários sistemas de persistência) , vale a pena gastar tempo e código, se não for, pra quê perder tempo?

Os bancos de dados relacionais não vão sair de linha nem tão cedo, dá uma testada num banco OO ou em um que persista em XML e você vai ver o que é viver na idade da pedra, especialmente quando alguém pedir pra você fazer um agrupamento de informações ou um relatório :lol:

F

Olá,

Cara essa semana eu acabei de fazer uma migracao dessas, tenho uma arquitetura que usei pra alguns desenvolvimentos que fiz. Minha persistencia e controle de transacoes era feito pelo Hibernate. Acabei de migrar pra usar o Spring, enviei pra um cliente e nao mudei uma linha de codigo do que tava la. Ou seja, enviei um novo jar da minha arquitetura e pedi pro cliente restartar o container web, so isso.

Na minha opiniao da sim, so que nem sempre vale a pena o esforco. Só se isso é um requisito senao esqueca.

]['s

Criado 20 de junho de 2005
Ultima resposta 1 de jul. de 2005
Respostas 82
Participantes 16