Quando eu estava implementando a DAO encontrei um problema, para eu listar todos os pedidos eu terei que buscar todos os outros dados de usuario, cliente, itens, parcelas. Mas até onde eu sei, a DAO não pode ter relacionamento com outras DAO (no caso a DAO de usuario, cliente e etc). Eu pensei em fazer um INNER JOIN no SELECT mas eu acho que isso iria fugir do padrão DAO.
public class PedidoDaoImpl extends GenericDao implements PedidoDao{
private final String sqlListar = "SELECT * FROM tb_pedido p INNER JOIN tb_usuario u ON p.id_usuario = u.id INNER JOIN tb_pessoa pj ON p.id_cliente = pj.id";
private final String sqlListarItens = "SELECT * FROM tb_iten i INNER JOIN tb_produto p ON i.id_produto = p.id WHERE id_pedido = ?";
private final String sqlListarParcelas = "SELECT * FROM tb_parcela WHERE id_pedido = ?";
public List<Pedido> listar() {
List<Pedido> pedidos = new ArrayList<Pedido>();
ResultSet rs = this.executeQuery(sqlListar);
try{
while(rs.next()){
Pedido pedido = new Pedido();
pedido.setId(rs.getInt("p.id"));
Usuario usuario = new Usuario();
usuario.setId(rs.getInt("u.id"));
usuario.setLogin(rs.getString("u.login"));
usuario.setNome(rs.getString("u.nome"));
usuario.setSenha(rs.getString("u.senha"));
pedido.setUsuario(usuario);
Cliente cliente = new Cliente();
cliente.setId(rs.getInt("pj.id"));
pedido.setCliente(cliente);
List<Item> itens = new ArrayList<Item>();
PreparedStatement pstmIten = this.getPreparedStatement(sqlListarItens);
pstmIten.setInt(1, pedido.getId());
ResultSet rsItem = this.executeCommand(pstmIten);
while (rsItem.next()) {
Item item = new Item();
item.setId(rsItem.getInt("i.id"));
Produto produto = new Produto();
produto.setId(rsItem.getInt("i.id_produto"));
produto.setNome(rsItem.getString("p.nome"));
produto.setPreco(rsItem.getFloat("p.preco"));
item.setProduto(produto);
item.setQuantidade(rsItem.getInt("i.quantidade"));
itens.add(item);
}
pedido.setItens(itens);
List<Parcela> parcelas = new ArrayList<Parcela>();
PreparedStatement pstmParcela = this.getPreparedStatement(sqlListarParcelas);
pstmParcela.setInt(1, pedido.getId());
ResultSet rsParcela = this.executeCommand(pstmParcela);
while (rsParcela.next()) {
Parcela parcela = new Parcela();
parcela.setId(rsParcela.getInt("id"));
parcela.setImposto(rsParcela.getFloat("imposto"));
parcela.setValor(rsParcela.getFloat("valor"));
parcela.setVencimento(rsParcela.getDate("vencimento"));
parcela.setSituacao(rsParcela.getString("situacao"));
parcelas.add(parcela);
}
pedido.setParcelas(parcelas);
}
return pedidos;
} catch (SQLException ex) {
Logger.getLogger(PedidoDaoImpl.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
}
Então esse é o meu problema, conto com a experiência e ajuda de vocês.
Obrigado.
Não sei se isso vai ajudar muito… mas acho que adicionar o Design Pattern MVC (Model View Controller) vai te dar uma pequena luz…
Esse Pattern indica a separar o software desenvolvido em três camadas: Model (modelagem de dados), View (interface do usuário) e Controller (regra de negócio).
Acho que te ajuda usar toda a junção, e tal, na regra de negócio.
Outra coisa que pode ajudar também é ter um atributo Pedido nas classes Item e Parcela, mas acho que já deve ter…
E pra comunicação com o banco de dados, ajuda bastante usar o framework Hibernate, que consegue buscar o próprio objeto nas consultas!
Não sei se isso vai ajudar muito… mas acho que adicionar o Design Pattern MVC (Model View Controller) vai te dar uma pequena luz…
Esse Pattern indica a separar o software desenvolvido em três camadas: Model (modelagem de dados), View (interface do usuário) e Controller (regra de negócio).
Acho que te ajuda usar toda a junção, e tal, na regra de negócio.
Outra coisa que pode ajudar também é ter um atributo Pedido nas classes Item e Parcela, mas acho que já deve ter…
E pra comunicação com o banco de dados, ajuda bastante usar o framework Hibernate, que consegue buscar o próprio objeto nas consultas!
Qualquer coisa, pode gritar![/quote]
Então deixa eu gritar: MVC não é Dado, Negócio e Interface!!!
Esse tipo de separação leva a sistemas procedurais (estruturas de dados + algoritmos) e é um anti pattern do catiço.
Modelo é dados + logica de dominio. Controller é um Mediador para interagir com o Modelo. View é uma representação dinâmica do Modelo.
De fato tanto o padrão DAO quanto padrão Facade são frequentemente sobre-utilizados, como pode ser fácilmente visto com uma busca simples aqui no GUJ. Contudo eu acredito q se vc está desenvolvendo um aplicativo usando JDBC (e as vezes frameworks realmente ñ são uma opção) então o uso de DAOs é mais q válido, é uma necessidade. No livro Real World JEE Patterns Adam Bien mostra uma muito interessante implementação do pattern DAO q é realmente genérico. Embora eu altualmente prefira essa implementação ao invés da popupla Entity-DAO ñ posso negar q ambas trazem vantagens bem como desvantagens. De qualquer forma a versão popular o DAO (Entity-DAO) é mais simples de implementar, especialmente se vc ñ tem muita experiência com reflection.
Obrigado a todos que responderam, mas acho que eu sei uma forma de resolver meu problema. Andei pensando e acho que posso fazer assim :
public class PedidoFacadeImpl implements PedidoFacade{
PedidoDao pedidoDao;
ItemFacade itemFacade;
ParcelaFacade parcelaFacade;
ClienteFacade clienteFacade;
UsuarioFacade usuarioFacade;
public PedidoFacadeImpl() {
pedidoDao = new PedidoDaoImpl(null, null);
itemFacade = new ItemFacadeImpl();
parcelaFacade = new ParcelaFacadeImpl();
clienteFacade = new ClienteFacadeImpl();
usuarioFacade = new UsuarioFacadeImpl();
}
public List<Pedido> listar() {
List<Pedido> pedidos = pedidoDao.listar();
for (int i = 0; i < pedidos.size(); i++) {
Pedido pedido = pedidos.get(i);
pedido.setCliente(clienteFacade.sarchById(pedido.getCliente().getId()));
pedido.setUsuario(usuarioFacade.searchById(pedido.getUsuario().getId()));
pedido.setItens(itemFacade.listar(pedido.getId()));
pedido.setParcelas(parcelaFacade.listar(pedido.getId()));
}
}
Bom deixa eu explicar melhor pra vocês. Isso é um trabalho de escola, e o professor quer que agente comece a fazer na mão as consultas, então ele não vai deixar usar Hibernate.
Ele quer também que agente use o DAO e o Facade.
No meu banco eu tenho a tabela pedido e nela eu tenho : id, id_cliente,id_usuario;
Eu também tenho a tabela Item que tem : id,id_pedido,id_produto,quantidade;
E em parcelas eu vou ter : id,id_pedido,valor,imposto,situacao,vencimento;
Até agora o que eu sei sobre o Facade e o DAO é que o DAO é quem lida com as regras de negócio e a Facade é quem tem as relações com outras classes.
Por favor me corrijam se eu estiver errado, mas acho que assim eu não estarei fora dos padrões!
Obrigado.
Ñ quero parecer arrogante kra, mas vc está errado.
A função do padrão DAO (Data Access Object) é, como o próprio nome diz, prover um meio de acessar informações q estão armazenadas em algum sistema de armazenamento secundário (ñ necessáriamente um banco de dados). A idéia é centralizar a lógica de acesso à esses dados p/ facilitar a manutenção de código e melhorar a legibilidade do código q o utiliza.
O padrão Facade, como é descrito pelo GOF, é um meio de vc modificar a interface de uma API problemática. Um exemplo de uso de Facade pode ser quando vc escreve a sua própria API p/ enviar e-mails pq a API do Java sucks!!! (ñ necessáriamente :))
Existe o padrão Service Facade (cuidade p/ ñ confundir) como descrito p/ J2EE Patterns da Sun. Esse padrão, embora muito popular no passado, é mais adequado p/ sistemas distribuidos onde o custo de serialização e troca de menssagens é muito alto p/ q possa ser feito através de uma interface com granularidade fina.
A lógica de negócios deve ficar nas classes de Modelo conforme descrição do GOF do padrão MVC.
Muito obrigado pela observação dev.rafael, esclareceu bastante cara, vlw mesmo.
Agora vou me debruça em cima desse padrão MVC pra entende ele e consegui implementa ele direitinho.
Vlw a ajuda de todo mundo ae!
[quote=dev.rafael]Ñ quero parecer arrogante kra, mas vc está errado.
A função do padrão DAO (Data Access Object) é, como o próprio nome diz, prover um meio de acessar informações q estão armazenadas em algum sistema de armazenamento secundário (ñ necessáriamente um banco de dados). A idéia é centralizar a lógica de acesso à esses dados p/ facilitar a manutenção de código e melhorar a legibilidade do código q o utiliza.
O padrão Facade, como é descrito pelo GOF, é um meio de vc modificar a interface de uma API problemática. Um exemplo de uso de Facade pode ser quando vc escreve a sua própria API p/ enviar e-mails pq a API do Java sucks!!! (ñ necessáriamente :))
Existe o padrão Service Facade (cuidade p/ ñ confundir) como descrito p/ J2EE Patterns da Sun. Esse padrão, embora muito popular no passado, é mais adequado p/ sistemas distribuidos onde o custo de serialização e troca de menssagens é muito alto p/ q possa ser feito através de uma interface com granularidade fina.
A lógica de negócios deve ficar nas classes de Modelo conforme descrição do GOF do padrão MVC.[/quote]
Rafael,
Os Session Facades tinham um papel de delimitador de transações no modelo tradicional. Como você substitui esse papel no modelo novo? Eu já li a respeito do uso de Stateful Beans para esse controle (e vi uma palestra do Gavin King há muito tempo atrás tratando do mesmo assunto). Foi assim que você resolveu ou você usou outro pattern?