Gostaria da opinião de vocês.
Como passar criterios de busca para um DAO de uma manira mais elegante.
ex:
class Funcionario
{
private char sexo;
private Departamento dep;
// setters and getters
}
class Departamento
{
private int codigoEdificio;
// setters and getters
}
class FuncionarioDAO
{
public Collection consultar() {}
}
class DepartamentoDAO
{
public Collection consultar() {}
}
Como eu implementaria o método consultar se quisesse consultar um funcionário pelo código do edificio, sendo que o mesmo é da classe departamento e não da classe funcionário.
O mais coerente que fizesse a busca pelo FuncionarioDAO, pois estou buscando funcionarios, mas baseado em um atributo de uma classe que está agregada a classe funcionário (departamento).
obs:
Não eu acho legal usar aquele hql na camada de negócio pois viola a lei d abstração de persisencia.
Se você tem um objeto Departamento dentro do funcionário, não vejo problemas em utilizar o ‘atributo do atributo’ (considerando que na tabela você teria essa estrutura também), como:
public class FuncionarioDAO(){
public Collection consultarById(Funcionario funcionario){
String sql = "SELECT * FROM FUNCIONARIO WHERE ID_DEPARTAMENTO = " + funcionario.departamento.getId() + ";
}
}
Pode ser.
Mas não ficaria deselegante.
Ter que ficar instanciando a classe funcionario e subclasses para fazer uma consulta.
Estava pensando em algo como
public class FuncionarioDAO(){
public Collection consultar(int numEdificio, char sexo){
//
}
public Collection consultar(int numEdificio){
//
}
}
Bem, eu optaria por receber o objeto, porque passando parâmetros eu teria de ter um método pra cada parâmetro. E se eu tivesse 50, 100, 1000 parâmetros…
E como foi dito no outro tópico, não é interessante espalhar os dados da implementação do objeto por aí, seria legal se o DAO não conhecesse como é a implementação do Funcionario.(Se bem que passando o objeto, dentro dele ele acabaria sabendo que ele possui um atributo chamado Departamento que possui um id.)
[quote]olhando rapidamente, prefiro como o Rafael postou, me parece um pouco mais OO.
so tiraria o sql de detro do DAO. [/quote]
tem outras formas, mas eu ja fiz carregando as consultas do xml em beans e tenho uma classe metodos estaticos que me retornam essas consultas.
no xml fica com tags mais ou menos assim:
<consulta codigo="codigo1"
sql="SELECT 1, 2 , 3 FROM table WHERE parametro1 = ?">
</consulta>
usando PreparedStatement vc substitui os parametros.
é por ae…
[]'s
<EDIT>
claro que depende das consultas, nesse caso eu tinha consultas bem chatas, que em arquivos properties ficariam dificeis de manter.
</EDIT>
Eu precisaria criar um método de consulta para cada consulta diferente?
Por exemplo:
public Collection consultarById(String query){...}
public Collection consultarBySexo(String query){...}
public Collection consultarByIdade(String query){...}
Não tem alguma forma de abstrair mais essa consulta, ou seria melhor mudar toda parte de persistência para utilizar algum framework, como Hibernate?
jgbt, qual API vc utiliza para parsear os XML’s para seus Beans?
a ideia é essa, cada metodo deve fazer somente o que é responsabilidade dele.
ter um metodo generico, mas cheio de if’s p/ montar a consulta, não me parece legal.
eu usei o castor, um framework p/ xml, não lembro o linnk agora, mas da uma procurada no google que vc deve achar.
[quote=jgbt]tem outras formas, mas eu ja fiz carregando as consultas do xml em beans e tenho uma classe metodos estaticos que me retornam essas consultas.
no xml fica com tags mais ou menos assim:
<consulta codigo="codigo1"
sql="SELECT 1, 2 , 3 FROM table WHERE parametro1 = ?">
</consulta>
[/quote]
Não entendi qual a diferença de colocar uma consulta no XML ou em um properties. O que você ganhou com esse XML? (Além da necessidade de ter que fazer o parser! :))
é que eram comsultas complexas, com varias subqueries.
ficava ruim de visualizar a consulta em um properties, numa unica linha.
e o bean tinha outras propiedades alem da query, que ficavam facil de mofificar, sem recompilar o codigo.
Se seus DAOs possuem tantos métodos de pesquisa diferentes que você está ficando maluco, considere seriamente a adoção de um framework O-R decente.
Eu já fui a favor de DAOs com “linguagens de consulta”, mas isso é completamente contra o uso que se deveria fazer de um DAO em si. Um DAO deveria ser usado quando você tem X consultas no banco, e no máximo, quem sabe, vai passar para 2X em alguns meses, mas não mais que isso. Uma das grandes vantagens (se você cosntruir DAOs bonitinhos) é que passar essa implementação para um Hibernate (exemplo, nenhuma lei) não é muito complicado mantendo a API do DAO.
Um outro ponto onde DAOs são problemáticos é montar relacionamentos. Muitas vezes voê acaba com métodos cheios de gambiarras para evitar trazer toda a sua estrutura de objetos do banco e ao mesmo tempo evitar NullPointerException.
Resumindo:
Use DAO quando você não vai rpecisar fazer nada além de CRUD. Se você precisa emitir relatórios ou fazer buscas complexas e parametrizadas, pode fazer com que estas operações com o SBD sejam efetuadas por outro componente, e deixem os DAOs no
public interface Dao{
public void create(Object o);
public Object read(int key);
public void update(Object o);
public void delete(Object o);
}
E meia dúzia de métodos de busca. Aliás: procure reutilizar o máximod e código dentro de um DAO, cuidade no modo como transforma um ResultSet em objeto, faça de maneira que todos os métodos de pesquisa possam reutilizar este método se possível.
não sou nenhum conhecedor profundo sobre DAO’s mas a interface que Shoes falor não poderia ficar assim :
[code] public interface Dao{
public void create(Object o);
public Object read(int key);
public void update(Object o);
public void delete(Object o);
public void relateObjects(Object oSouce, Object oDestination, String sRelation);
public void unrelateObjects(Object oSouce, Object oDestination, String sRelation);
public void save();
}[/code]
onde os métodos de relate e unrelate fariam os updates da campos relacionados(chaves estrangeiras e primárias) e o método save salvaria tudo que estivesse pronto para salvar.
Poderíamos ter algo assim:
update table_aluno set ..... ;--Seta os campos
update table_aluno set aluno2disciplina = null;--parte do relacionamento
update table_aluno set aluno2disciplina = 844558 ;-- um id de disciplina
commit;
Acho que isso não deve estar muito bonito.
Como podemos tratar relacionamentos de forma correta ?? (sem utilizar hibernate ) .
Na verdade, a “interface” era uma piada com o CRUD
Um DAO abstrato (ou uma interface) com métodos de negócio definidos não é muito útil, a menos que você goste de casts.
Você tme um acoplamento de controle muito grande aí. Ao passar “o que deve ser feito” como um parãmetro, você prende a implementação do seu método no cliente, o que é bem ruim. Mais detalhes aqui.
Além do que, objetos sabem de uma relação através de seus atributos. Se você fosse implementar isso, o dao deveria saber que o aluno têm uma relação com cálculo, e quando necessário atualzar cálculo também.
O que não é muito prático dependendo do caso. Sem lazy loading você geralmente (como falei) vai ter vários métodos fazendo a mesma coisa, só que com mais ou menos detalhes, para não ter uma NPE.
Com DAOs você não tem muita escolha, tem muitas gambiarras. O DAO é orientado por funcionalidade, então se eu preciso de um relacionamento para executar uma tarefa, mas em outra eu não rpeciso trazer este relacionamento todo (e isso pdoe envolver vários níveis), vou ter métodos diferentes que fazem quase a mesma coisa.
[quote=pcalcado]
Com DAOs você não tem muita escolha, tem muitas gambiarras. O DAO é orientado por funcionalidade, então se eu preciso de um relacionamento para executar uma tarefa, mas em outra eu não rpeciso trazer este relacionamento todo (e isso pdoe envolver vários níveis), vou ter métodos diferentes que fazem quase a mesma coisa.[/quote]
Não existe nenhum padrão de projeto para acabar com este problema do DAO?
Você tme um acoplamento de controle muito grande aí. Ao passar “o que deve ser feito” como um parãmetro, você prende a implementação do seu método no cliente, o que é bem ruim. Mais detalhes aqui.
[/quote]
ae shoes,
não é a primeira vez que vc cita esse livro como refererencia.
ja to me coçando p/ comprar, vale a pena mesmo?
[quote=maikonaraujo]
Não existe nenhum padrão de projeto para acabar com este problema do DAO?[/quote]
Não que eu conheça.
O que você poderia tentar fazer é criar listeners e interceptadores (talvez suando metadados) que sabem quando o estado de um objeto foi significantemente alterado e o persista, e um mecanismo de lazy-loading com proxies dinâmicos.