Dúvida sobre DAO

15 respostas
Arthur.hvt

Olá. Estou tendo uma dúvida em relação ao padrão DAO em relação a modelagem e gostaria de saber se alguém ja resolveu isso.

Por exemplo, imagine que eu tenho no banco de dados 3 tabelas: Casa, Quarto e Cama
Na tabela Cama eu tenho as colunas: id, idQuarto (FK)
Quarto: id, idCasa (FK)
Casa: id

E na minha aplicação eu tenho os seguintes POJO:

public class Cama {

private int id;
private Quarto quarto;

//gets e sets

}
public class Quarto {

private int id;
private Casa casa;
private Set<Cama> camas;

//gets e sets

}
public class Casa {

private int id;
private Set<Quarto> quartos;

//gets e sets

}

Como eu teria que criar as classes DAO para poder pegar todos os dados do banco de dados?
Gostaria de fazer o menor numero de requisições possiveis (a qtde de dados é grande, e sao varias tabelas) e eu nao posso alterar nada no banco de dados. Obrigado.

15 Respostas

tveronezi

DAO é apenas um objeto que encapsula como vc recupera e persiste os dados da tua camada de persistencia (banco de dados, ws, arquivo texto etc). Como vc implementa o código interno disso depende de vc.

Exemplo de interface:

interface CasaDAO {
  Casa findById(int id);
  Set<Quarto> findQuartoByCasaId(int id);
  Set<Cama> findCamaByQuartoId(int id);
  Set<Cama> findCamaByCasaId(int id);
  void addCamasToQuarto(int quartoId, Set<Cama> camas);
.
.
.
}
drsmachado

Vai usar DAO e qual será o modelo de persistência? JDBC? ORM?

Arthur.hvt

Uso JDBC. Gostaria de usar Hibernate mas o código ja esta todo em JDBC e teria que mudar muita coisa pra portar.

Eu gostaria de saber se eu teria que fazer um DAO pra cada classe (CasaDAO, QuartoDAO e CamaDAO) ou eu pegaria isso tudo direto do DAO de casa.

drsmachado

A resposta é: depende.
Depende de como você pretende que isso seja feito.
Por exemplo, se só vai usar os dados de quarto e cama junto de casa, não tem por que ter DAOs separados…

Arthur.hvt

Na verdade eu acho que eu preciso de DAOS separados, porque vai ser feito várias outras coisascom quarto e cama... O que eu nao consigo entender é como eu posso pegar todos esses dados do banco de uma vez só com esses DAOS separados e sem que um se relacione com o outro.

Por exemplo, se eu fosse implementar assim:

public class CasaDao {

    public List<Casa> getCasas() throws Exception {

        ResultSet rs = null;
        Connection conexao = null;
        PreparedStatement ps = null;

        List<Casa> casas = null;

        try {
            conexao = connectionFactory.getConexaoExterna();

            ps = conexao.prepareStatement("SELECT * FROM casas");
            ps.execute();

            casas = new ArrayList();

            while (rs.next()) {

                //preciso pegar o id e os quartos. O id tudo bem, mas e os quartos?
                int id = rs.getInt("id");

                casas.add(new Casa(id));
            }

            return casas;
        } catch (Exception e) {
            throw new Exception("Erro ao buscar as casas", e);
        } finally {
            conexao.close();
        }
    }
}
public class QuartoDao {

    public List<Quarto> getQuartos() throws Exception {

        ResultSet rs = null;
        Connection conexao = null;
        PreparedStatement ps = null;

        List<Quarto> quartos = null;

        try {
            conexao = connectionFactory.getConexaoExterna();

            ps = conexao.prepareStatement("SELECT * FROM quartos");
            ps.execute();

            quartos = new ArrayList();

            while (rs.next()) {

                //preciso pegar o id, casa e camas. Como eu pego a casa e as camas?
                int id = rs.getInt("id");

                quartos.add(new Quarto(id));
            }

            return quartos;
        } catch (Exception e) {
            throw new Exception("Erro ao buscar os quartos", e);
        } finally {
            conexao.close();
        }
    }
}
public class CamaDao {

    public List<Cama> getCamas() throws Exception {

        ResultSet rs = null;
        Connection conexao = null;
        PreparedStatement ps = null;

        List<Cama> camas = null;

        try {
            conexao = connectionFactory.getConexaoExterna();

            ps = conexao.prepareStatement("SELECT * FROM camas");
            ps.execute();

            camas = new ArrayList();

            while (rs.next()) {

                //preciso pegar o id e quarto. Como pego o quarto?
                int id = rs.getInt("id");

                camas.add(new Cama(id));
            }

            return camas;
        } catch (Exception e) {
            throw new Exception("Erro ao buscar as camas", e);
        } finally {
            conexao.close();
        }
    }
}
Dani_Gomes

Arthur.hvt.
Só para entender, o seu banco não possui relacionamentos?

Pelo que você diz acima, idCasa, é uma chave estrangeira e para ter uma chave estrangeira tem que ter um relacionamento. Então segundo o seu dizer acima o seu banco possui relacinamento.

conexao = connectionFactory.getConexaoExterna();  
  
            ps = conexao.prepareStatement("SELECT * FROM casas");  
            ps.execute();  
  
            casas = new ArrayList();  
  
            while (rs.next()) {  
  
                //preciso pegar o id e os quartos. O id tudo bem, mas e os quartos?  
                int id = rs.getInt("id");  
  
                casas.add(new Casa(id));  
            }  
  
            return casas;

Neste caso você está dizendo pro banco selecionar os dados que estão na tabela casas.
E se nesta tabela não possui dados da tabela quarto relacionada, não irá aparecer nenhum dado de quarto de maneira alguma, ai o problema está no seu SQL.

G

só lembrando que se vc utiliza JPA/hibernate vc não deve utilizar DAO a não ser para casos especiais, pois o framework já faz o papel do pattern de isolar as regras de banco pra vc.

fantomas

Oi Arthur.hvt,

Os ORMs surgiram a partir deste seu problema, ou seja, construir uma arvore de objetos a partir do menor numero de acesso ao banco de dados. O ORM deduz a instrução SQL (inclusive os relacionamentos), submete a instrução no banco de dados e constrói a árvore de objetos a partir do resultado automaticamente. Dito isto,  para perceber que a situação não é tão simples assim.

O que você poderia fazer é utilizar algum tipo de ORM bem leve para não radicalizar tanto,  que o teu contexto é puramente JDBC. Para isto tem o Ebean [url]http://www.avaje.org/[/url], tem tambem o Persist [url]http://code.google.com/p/persist/[/url] e etc... normalmente estes ORMs são bem restritos em termos de números de tipos de bancos de dados acessados por eles. A curva de aprendizado é bem pequena, no máximo 2 dias e o objetivo principal é ajudar na construção da arvore de objetos e reduzir a complexidade na camada de acesso a dados.

Fora isto não vejo alternativa a não ser fazer vários acessos e construir a arvore de objetos "não unha" mesmo.

flws

drsmachado

Eu enfatizo o coro de @Dani Gomes. Suas tabelas são relacionadas? Se forem, você pode, com certeza, criar uma query que obtenha todos os elementos que necessita, independente de possuir DAOs específicas.

@gambazinho, o uso do DAO, mesmo com ORM, é feito por muitos desenvolvedores para manter-se um total isolamento da estrutura, pois, de outra forma, haveria a dúvida: “persisto na camada model ou crio outra camada?”

G

drsmachado:
Eu enfatizo o coro de @Dani Gomes. Suas tabelas são relacionadas? Se forem, você pode, com certeza, criar uma query que obtenha todos os elementos que necessita, independente de possuir DAOs específicas.

@gambazinho, o uso do DAO, mesmo com ORM, é feito por muitos desenvolvedores para manter-se um total isolamento da estrutura, pois, de outra forma, haveria a dúvida: “persisto na camada model ou crio outra camada?”


o rponte e outros devs da lista de JSF discordam severamente desse ponto de vista e eu particularmente acho que o ideal é realmente evitar um DAO para coisas idiotas como entity.find(entity) ou entity.merge(entity) ou entity.remove(entity) pra que criar um dao pra encapsular algo que já está encapsulado? LOL agora se vc tem uma daquelas querys brutas onde é viável por N questões, entre elas performance, usar jdbc ou mesmo a nativeQuery aí é mais que justificável, é aconselhável isolar essa query num DAO.
Mas o Sr. é já é um GUJ Expert, quem sou eu para discordar.

drsmachado

gambazinho:
drsmachado:
Eu enfatizo o coro de @Dani Gomes. Suas tabelas são relacionadas? Se forem, você pode, com certeza, criar uma query que obtenha todos os elementos que necessita, independente de possuir DAOs específicas.

@gambazinho, o uso do DAO, mesmo com ORM, é feito por muitos desenvolvedores para manter-se um total isolamento da estrutura, pois, de outra forma, haveria a dúvida: “persisto na camada model ou crio outra camada?”


o rponte e outros devs da lista de JSF discordam severamente desse ponto de vista e eu particularmente acho que o ideal é realmente evitar um DAO para coisas idiotas como entity.find(entity) ou entity.merge(entity) ou entity.remove(entity) pra que criar um dao pra encapsular algo que já está encapsulado? LOL agora se vc tem uma daquelas querys brutas onde é viável por N questões, entre elas performance, usar jdbc ou mesmo a nativeQuery aí é mais que justificável, é aconselhável isolar essa query num DAO.
Mas o Sr. é já é um GUJ Expert, quem sou eu para discordar.

Eu compreendo teu ponto de vista, o que disse não é, nem nunca será verdade absoluta.
Por exemplo, eu trabalho num sistema que emprega o design pattern facade e, não há DAOs, com hibernate.
Funciona muito bem, mesmo com queries gigantescas.

G

drsmachado:
Eu compreendo teu ponto de vista, o que disse não é, nem nunca será verdade absoluta.
Por exemplo, eu trabalho num sistema que emprega o design pattern facade e, não há DAOs, com hibernate.
Funciona muito bem, mesmo com queries gigantescas.

é isso aí! ^^
perdoe-me se me excedi.
abs!

tveronezi

DAO é apenas um pattern. No mundo JPA ele pode ser chamado de EAO (Entity Access Object).

Arthur.hvt

Entao seria melhor mesmo eu pegar todos os dados a partir de uma unica DAO (Casa, nesse caso) e utilizando uma query gigante usando inner joins? Realmente essa é a unica forma que eu vejo que pode ser feita pra pegar todos os dados de uma vez com o menor numero de chamadas.

ErickRAR

Sim, você pode fazer assim, e nem precisa de uma query gigante. Só 2 joins, eu acho. O negócio é, isso pode ser levado em consideração se você sempre for trabalhar com o objeto Casa.
Agora imagine que você só precisa de um quarto: Terá que pegar a casa e todos os quartos, apenas para utilizar um único quarto. Isso pode dar uma queda de desempenho.

Mas enfim, tudo é relativo. Cada caso é um caso.

Criado 26 de junho de 2012
Ultima resposta 28 de jun. de 2012
Respostas 15
Participantes 7