Classe DAO

Bom dia Galera,

É o seguinte, estou desenvolvendo uma agenda usando bd firebird. Eu faço conexao sem problemas mas minha duvida é com relação a classe DAO. O que deve ter na classe DAO? Desenvolvi botoes de navegação, estes botoes tem que acessar a classe DAO? eu ja fiz a aplicação funcionar colocando os dados em um array, mas acredito que nao seja uma boa pratica uma vez que TODOS os contados da agenda estarao no array podendo deixar a memoria do java cheia sem necessidade, entao quero trabalhar trazendo os dados diretamente do ResultSet. O que voces acham e qual é a melhor pratica? Pensem que o sistema vai crescer muito…

Obrigado galera.

o dao vc vai usar numa situação assim

Cliente c = daoCliente.getCliente(666); // pega o id 666 da tabela

agora, se vc tem botoes vc pode raciocinar a sua aplicacao em termos de MVC

M modelo (a classe Cliente, por exemplo, esta aqui)
C controller (sabe o que fazer com o modelo e manda para a view)
V view (mostra os dados, tem os botoes, etc).

O que vc tem que fazer? coordenar estas camadas. É claro que vc pode ter um botao e nele carregar uma string que venha do banco de dados, mas isso com o tempo vira um pesadelo. Agora um botao que invoca um metodo para o controller é mais divertido.

Por exemplo, vc tem um campo para digitar o id e vc quer recuperar este cliente.

O botao, na view, ao ser pressionado, envia o conteudo desse campo para um método no Controller.

O controller acessa o DAO e recupera este cara.

O dao retorna para a view e ela sabe o que fazer com este cara.

Bem, basta entender o que significa DAO que você vai saber onde aplicá-lo… veja:

DAO = Data Access Object…
Ou seja, é um objeto responsável pelo acesso aos dados… recuperar, salvar, atualizar, deletar… conceito de CRUD…
CRUD? Create-Retrieve-Update-Delete…

Como falaram ai em cima, usando um modelo MVC (Model - View - Controller) o DAO é uma boa opção na minha opinião…
Um botão na sua View dispara um método no Controller que acessa um DAO pra recuperar ou fazer alguma outra coisa com os dados, e depois exibir os resultados de novo na sua View…

Bom, eu criei uma classe ClienteDAO que tem um metodo getListaCliente que retorna um ResultSet:

[code]public class ClienteDAO {
private ResultSet rs;
private Statement stm;
private Connection conn = ConnectionFactory.getConnection();

public ClienteDAO (){
	
}
public ResultSet getClienteDAO () throws SQLException{
	this.stm = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
	this.rs = stm.executeQuery("SELECT * FROM CLIENTE");
	
	return this.rs;
}

[/code]

tenho uma classe que é um frame de Cliente e tenho o metodo do botao:

class BtnNextListener implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
						
			try {
				
				if (rs.next()) {
					txtNome.setText(rs.getNString(2));
					btnPrevious.setEnabled(true);
					btnLast.setEnabled(true);
					btnFirst.setEnabled(true);
				} else {
					btnNext.setEnabled(false);
					btnLast.setEnabled(false);
				}
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
								e1.printStackTrace();
			}

		}

	}

esta classe acima esta dentro da minha classe frame que tem ResultSet rs, que é este que vemos no Listener. Mas quando clico no botao “next” ele acusa que o resultset esta fechado. O que posso ter feito de errado??

Se fosse na mesma classe, voce poderia acessá-lo normalmente, mas como estão em classes diferentes, você precisa de um ResultSet no seu Frame… assim:

[code] class BtnNextListener implements ActionListener {

     public void actionPerformed(ActionEvent e) {  
         // TODO Auto-generated method stub  
                       
         try {  
             // nesse ponto vc chama seu DAO, voce quer uma lista de clientes, então é responsabilidade do DAO, ele que se vire pra te trazer o ResultSet...
             ResultSet rs = new ClienteDAO().getClienteDAO();
             if (rs.next()) {  
                 txtNome.setText(rs.getNString(2));  
                 btnPrevious.setEnabled(true);  
                 btnLast.setEnabled(true);  
                 btnFirst.setEnabled(true);  
             } else {  
                 btnNext.setEnabled(false);  
                 btnLast.setEnabled(false);  
             }  
         } catch (SQLException e1) {  
             // TODO Auto-generated catch block  
                             e1.printStackTrace();  
         }  

     }  

 }[/code]

Não, lonnewolf, sua classe DAO não deve retornar um ResultSet, mas uma coleção de Clientes.

Você deve criar a classe Cliente, que deve ter apenas os atributos (e seus get’s e set’s), consultar o banco, preencher os atributos dos objetos Cliente e retornar essa lista de clientes.

Se o DAO retorna um resultset ele não é um DAO, é um helper que acessa o banco de dados.

O começo da apostila FJ-21 da caelum tem um bom exemplo de dao e a apostila é gratis.

Entao galera, esta é exatamente minha duvida. Imagine que eu de um Select * From Cliente, eu vou entao retornar um array, list ou algo do tipo de Cliente, certo? So que se eu tiver 1000 clientes, vou ter que instanciar 1000 objetos Cliente no array. Isto não é ruim se for pensar em memoria ou algo do tipo? Me corrijam pois sou iniciante em Java. Sou acostumado com linguagem OE.

Vlw galera.

[quote=marcelo.bellissimo]Se fosse na mesma classe, voce poderia acessá-lo normalmente, mas como estão em classes diferentes, você precisa de um ResultSet no seu Frame… assim:

[code] class BtnNextListener implements ActionListener {

     public void actionPerformed(ActionEvent e) {  
         // TODO Auto-generated method stub  
                       
         try {  
             // nesse ponto vc chama seu DAO, voce quer uma lista de clientes, então é responsabilidade do DAO, ele que se vire pra te trazer o ResultSet...
             ResultSet rs = new ClienteDAO().getClienteDAO();
             if (rs.next()) {  
                 txtNome.setText(rs.getNString(2));  
                 btnPrevious.setEnabled(true);  
                 btnLast.setEnabled(true);  
                 btnFirst.setEnabled(true);  
             } else {  
                 btnNext.setEnabled(false);  
                 btnLast.setEnabled(false);  
             }  
         } catch (SQLException e1) {  
             // TODO Auto-generated catch block  
                             e1.printStackTrace();  
         }  

     }  

 }[/code][/quote]

Marcelo, quando eu fiz isto, o botao nao navegava, pois ele sempre criava um novo select, mas resolvi isto instanciando o rs logo no começo da classe.

Mas vlw a dica.

Se você selecionar 1000 clientes de uma vez isso não seria bom para a performance independente de ser numa lista de objetos ou não.
A questão é, você vai precisar buscar 1000 clientes no banco de uma vez no seu programa? Caso precise listar esses clientes, não seria melhor pensar numa forma de paginar esses dados?

entao, necessario nao eh, mas em uma tela de busca onde o usuario seleciona os criterios da pesquisa, pode carregar muitos dados (1000 é exagero so para poder dar um exemplo bem forçado). Voces entenderam qual é a idéia?
Entao ta, se eu trouxer uma lista de clientes do ClientesDAO, para navegar nela terei de colocar ponteiros certo? Este ponteiro seria um atributo da classe?

[quote=lonnewolf]entao, necessario nao eh, mas em uma tela de busca onde o usuario seleciona os criterios da pesquisa, pode carregar muitos dados (1000 é exagero so para poder dar um exemplo bem forçado). Voces entenderam qual é a idéia?
Entao ta, se eu trouxer uma lista de clientes do ClientesDAO, para navegar nela terei de colocar ponteiros certo? Este ponteiro seria um atributo da classe?[/quote]

Não existe ponteiros em Java, no caso você criaria uma lista, um ArrayList por exemplo e adicionaria elementos e acessaria através de um índice numérico, tipo:

ArrayList<Cliente> lista = new ArrayList<Cliente>();

// adicionando clientes à lista
lista.add(objeto_cliente);

// lendo clientes da lista
Cliente c1 = lista.get(0); // primeiro cliente adicionado à lista
Cliente c2 = lista.get(2); // segundo cliente

[quote=lonnewolf][quote=marcelo.bellissimo]Se fosse na mesma classe, voce poderia acessá-lo normalmente, mas como estão em classes diferentes, você precisa de um ResultSet no seu Frame… assim:

[code] class BtnNextListener implements ActionListener {

     public void actionPerformed(ActionEvent e) {  
         // TODO Auto-generated method stub  
                       
         try {  
             // nesse ponto vc chama seu DAO, voce quer uma lista de clientes, então é responsabilidade do DAO, ele que se vire pra te trazer o ResultSet...
             ResultSet rs = new ClienteDAO().getClienteDAO();
             if (rs.next()) {  
                 txtNome.setText(rs.getNString(2));  
                 btnPrevious.setEnabled(true);  
                 btnLast.setEnabled(true);  
                 btnFirst.setEnabled(true);  
             } else {  
                 btnNext.setEnabled(false);  
                 btnLast.setEnabled(false);  
             }  
         } catch (SQLException e1) {  
             // TODO Auto-generated catch block  
                             e1.printStackTrace();  
         }  

     }  

 }[/code][/quote]

Marcelo, quando eu fiz isto, o botao nao navegava, pois ele sempre criava um novo select, mas resolvi isto instanciando o rs logo no começo da classe.

Mas vlw a dica.[/quote]

O problema com essa abordagem, eu acho (não tenho certeza de como o GarbageCollector trata isso), é que o seu ResultSet vai ficar lá, na memória, enquanto sua classe existir… seria uma boa opção setar o seu ResultSet como null após usar, e sempre instanciar ele quando precisar, justamente pelo fato dele poder conter uma lista grande de resultados… ai sim, vai atolar sua aplicação… alguém confirma minha teoria?

numa implementação simples de DAO vc também pode ficar com uma connection aberta, por isso é bom observar que todo ‘open’ precisa de um ‘close’.

Galera, vlw as dicas. A ajuda de voces me esclareceu muitas coisas. Eu trouxe uma lista de Cliente do ClienteDAO e na minha classe que é frame de cliente eu trato as informaçoes. Eu só estou com a pulga atras de orelha com relação a quantidade de informaçoes na lista. Mas mais pra frente veremos o que acontecerá.

Um forte abraço galera.