Problema Com JDBC

Boa tarde a todos.

Meu nome é Douglas, sou aluno do 3º semestre de BSI, e trabalho com suporte a algum tempo; Atualmente estou tentando aprender e melhorar mais meus conhecimentos na área de desenvolvimento, mais especificamente JAVA. Já possuo alguma experiência com Delphi, e POO, mas no entando estou apenas “Iniciando” no caminho do Java.

Pois bem, aqui está uma breve descrição do que venho fazendo:

Recentemente criei, utilizando JDK 1.5.0 update 9 e NetBeans 5.5 duas classes: A classe TesteJDBC e a classe InterfaceGrafica. A Classe TesteJDBC funciona perfeitamente, e apresenta as seguintes funcionalidades:

  • Carrega o Driver ponte JDBC-ODBC e se conecta a um Banco de Dados Access chamado Cds, que está localizado na pasta do projeto; Todas as configurações de ODBC do windows já estão ok e o acesso ocorre perfeitamente, apartir do método Conecta();
  • Possui um método CriaTabelas que pode ser chamado para gerar uma tabela chamada Cds com dois campos (Titulo e NCopias) o qual utilizei apenas uma vez a título de aprendizado, não sendo o mesmo utilizado em minha aplicação já que a tabela já está criada;
  • Possui um método InsereDados, trabalhando com Prepared Statement, Recebendo dois valores (String e Int) para repassar como um novo registro da tabela;

No mesmo pacote possuo a classe InterfaceGrafica; Nada mais é que uma classe com um botão e duas JTextBoxes para receber o valor do Titulo e do numero de copias para que possa ser repassado para o método InsereDados cadastrar na tabela, no evento de clique do botão.

Eis o problema:

Como o método InsereDados é um método da classe TesteJDBC e eu não posso declará-lo como static pois o prepared statement não permite, como faço para chamá-lo ao clicar o botão?
Pois para chamar o mesmo no actionEvent do botão eu irei necessitar de chamá-lo apartir do nomeDaInstancia.Metodo, ou seja, algo como novo.InsereDados, necessitando de instanciar a mesma dentro do actionEvent do botão. Se eu fizer isso funciona, mas TODA vez que eu clicar no botão e executar um cadastro, a classe será novamente instanciada…

Realmente não sei a estrutura correta para que eu possa fazer o correto: Instanciar o objeto e apenas chamar seu método para inserir os dados obtidos ao clicar o botão da InterfaceGrafica, apartir das caixas de texto.

Seguem os códigos fonte:

TesteJDBC.java:

[code]package bancodedados;
import java.sql.*;
import javax.swing.JOptionPane;

public class TesteJDBC{
String url= “jdbc:odbc:Cds”;
Connection con;

public Connection Conecta(){
    try
        {
            System.out.println("Iniciando a conexão com o BD...");
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
            con = DriverManager.getConnection(url,"","");
            System.out.println("Banco de Dados Ok e Pronto...");
            return con;
        }
    catch(ClassNotFoundException cnf)
        {
            System.out.println("Houve uma ClassNotFoundException: "+cnf);
            return null;
        }
    catch(SQLException sql)
        {
            System.out.println("Houve uma SQLException: "+sql);
            return null;
        }
}



    public void CriaTabelas(){
        try {
            Statement st = con.createStatement( );
            st.executeUpdate("create table Cds(Titulo varchar(32),NCopias integer);");
            System.out.println("Tabela Criada com Sucesso!");
            st.close();
            }
        catch(SQLException sql)
            {
            System.out.println("Erro! "+sql);
            }
    }

    public void InsereDados(String a, int b){
        try {
            PreparedStatement st2 = con.prepareStatement("insert into Cds values(?,?)" );
            st2.setString(1,a);
            st2.setInt(2,b);
            st2.execute();
            st2.close();
            con.close();
            System.out.println("Dados Adicionados Com Sucesso!");
        }
        catch(SQLException sql)
        {
            System.out.println("Erro! "+sql);
        }
    }

  }[/code]

InterfaceGrafica.java


package bancodedados;

import bancodedados.TesteJDBC;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class InterfaceGrafica extends JFrame implements ActionListener
{
    JButton botao;
    JPanel panel;
    JTextField texto,texto2;
    String a,intSemConverter;
    int intConvertido;
   
    
    public InterfaceGrafica() {
         super("BancoDeDados 1.0");
     }
     
     public void criaJanela()
     {        
         texto = new JTextField("");
         texto2 = new JTextField("");
         panel = new JPanel();
         panel.setLayout(new GridLayout(2, 1));
                 
         botao = new JButton("Clique para Cadastrar!");
         botao.addActionListener(this);
         
         panel.add(texto);
         panel.add(botao);
         panel.add(texto2);
         
         getContentPane().add(panel, BorderLayout.CENTER);
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         
         pack();
         setVisible(true);        
     }
     
         
     public void actionPerformed(ActionEvent event)
     {
         TesteJDBC novo = new TesteJDBC();
         novo.Conecta();
 
         
         a = texto.getText();
         intSemConverter = texto2.getText();
         intConvertido = Integer.parseInt(intSemConverter);
         
         novo.InsereDados(a,intConvertido);
         
               
     }
     
     public static void main(String args[])
     {
         
         InterfaceGrafica ex2 = new InterfaceGrafica();
         ex2.criaJanela();
         
         
     }
 }  

Repare que deste modo FUNCIONA, mas cria uma instancia de TesteJDBC a todo clique do botão. Colocar um If com um contador para evitar uma segunda execução (If contador == 0) {
faz instancia
contador++;
}

nao funciona, pois volta o problema de não reconhecer o novo.InsereDados, como se a instancia nao estivesse sendo criada.

Creio que tenha sido um pouco confuso… e acho que a maneira que estou utilizando para trabalhar com o cadastramento deve estar incorreto, portanto agradeço qualquer ajuda. Realmente não sei como vou colocar isso pra funcionar sem redundâncias ^^

Obrigado a todos,

Douglas Vargas

Ps. Agradecimento ao portal da GUJ e pelo tutorial sobre Swing, no qual tem base a parte gráfica da minha aplicação. A maior parte do código relativo ao Swing foi baseado nesse tutorial, então muito obrigado :slight_smile:

Esse tutorial pode ser util para você:

http://www.guj.com.br/java.tutorial.artigo.155.1.guj

Hum… muito obrigado!
Estou lendo aqui… mas me pareceu bem interessante. Basicamente esse PicoContainer vai possibilitar essa minha interação de métodos de classes diferentes sem a instanciação toda vez que eu precisar utilizá-los, certo?
Vou tentar fazer aqui. Qualquer duvida eu falo.

Muito obrigado de novo!

Weeeeeeeeee!
Acho q consegui!

Ainda tenho uma duvidazinha, mas vamos ao que interessa:
(Ainda não sei se está certo eheheheh) ^^

Segue o novo código fonte do InterfaceGrafica.java:

[code]package bancodedados;

import bancodedados.TesteJDBC;
import java.awt.;
import java.awt.event.
;
import javax.swing.*;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.defaults.DefaultPicoContainer;

public class InterfaceGrafica extends JFrame implements ActionListener
{
JLabel label1,label2;
JButton botao;
JPanel panel;
JTextField texto,texto2;
String a,intSemConverter;
int intConvertido;
MutablePicoContainer pico = new DefaultPicoContainer();

public InterfaceGrafica() {
    super("BancoDeDados 1.0");
 }
 
 public void criaJanelaEContainer()
 {        
     label1 = new JLabel("Titulo:");
     label2 = new JLabel("Nº Cópias");
     texto = new JTextField("");
     texto2 = new JTextField("");
     panel = new JPanel();
     panel.setLayout(new GridLayout(3,2));
             
     botao = new JButton("Clique para Cadastrar!");
     botao.addActionListener(this);
     
     panel.add(label1);
     panel.add(texto);
     panel.add(label2);
     panel.add(texto2);
     panel.add(botao);

     
     getContentPane().add(panel, BorderLayout.CENTER);
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
     pack();
     setVisible(true);        
 
     pico.registerComponentImplementation(TesteJDBC.class);
     
     
      
    
     

 }
 
     
 public void actionPerformed(ActionEvent event)
 {
     TesteJDBC teste = (TesteJDBC) pico.getComponentInstance(TesteJDBC.class);
     a = texto.getText();
     intSemConverter = texto2.getText();
     intConvertido = Integer.parseInt(intSemConverter);
     
     teste.Conecta();
     teste.InsereDados(a,intConvertido);
   
     
           
 }
 
 public static void main(String args[])
 {
     
     InterfaceGrafica ex2 = new InterfaceGrafica();
     ex2.criaJanelaEContainer();
     
     
 }

}
[/code]

É isso mesmo? Ainda não sei se está correto.

Tipo, se eu entendi bem, no trecho de código

pico.registerComponentImplementation(TesteJDBC.class);

eu registrei a classe TesteJDBC.class como uma classe que eu irei instanciar utilizando o PicoContainer;
e aqui

TesteJDBC teste = (TesteJDBC) pico.getComponentInstance(TesteJDBC.class);

Eu requisitei uma instancia da mesma através do picoContainer.
E toda vez que eu clicar no botão esse trecho de código não irá criar uma nova instancia da classe TesteJDBC, mas sim apenas requisitar uma instância da mesma… que o pico ja criou e vai reutilizar… certo?

Ainda restou essa dúvida ^^

Abraços, e muito obrigado novamente!

Douglas Vargas

Mais uma coisa:
Ouvi falar que o padrão de projeto (Design Pattern) MVC - Model View Controller também serve para resolver esse tipo de problema.
Estou pesquisando pra saber como funciona… agradeço se alguem souber me passar um exemplo de como eu aplicaria o MVC a minha aplicação. Já sei que eu teria de dividir as tarefas, de modo que a interface gráfica chame um controlador que por sua vez iria chamar a minha classe responsável pela conexão com o banco. Mas realmente ainda não descobri como implementar isso.

Se alguem tiver alguma dica, agradeço!

Douglas Vargas