Olá pessoal do GUJ,
estou treinando um pouco de conexão com banco de dados e interface gráfica. Porém me deparei com um obstáculo: tenho uma interface gráfica com 1 text field (tfQuery) onde insiro o comando SQL, 1 button (btExec) que executa o comando SQL do text field, e uma table (table) onde quero que apareça o resultado de um SELECT.
Quero que a table seja dinâmica. Exemplo:
SELECT * FROM Aluno <- 3 colunas devem aparecer
SELECT * FROM Livro <- 7 colunas devem aparecer
Mas, quando mando executar o código que já tenho pronto (código que eu fiz pegando exemplo do livro “JAVA how to program” do Deitel), ele dá NullPointerException aqui:
public int getColumnCount() {
try {
return(mdt.getColumnCount()); //exatamente aqui a exceção!
}catch(SQLException e) {
JOptionPane.showMessageDialog(null, "Erro ao retornar o número de colunas!!", "Erro!", JOptionPane.PLAIN_MESSAGE);
}
return(0);
}
Não tenho a menor noção do que pode estar faltando, mas gostaria de uma ajudinha. Se precisarem de mais informações, é só pedir!
Obrigado.
mdt está null.
De onde ele vem?
Bom, vamos lá.
private void btExecActionPerformed(java.awt.event.ActionEvent evt) {
Table table = new Table();
table.setQuery(taQuery.getText()); //seta o comando
}
public void setQuery(String Query) {
Conexao con = new Conexao();
con.getConexao();
modelo.executeQuery(Query); //executa o comando
con.closeConexao();
}
public void executeQuery(String Query) {
try {
con.rowSet.setCommand(Query); //seta o comando no rowset
con.rowSet.execute();
mdt = con.rowSet.getMetaData(); //aqui ele pega o metadata
con.rowSet.last();
nor = con.rowSet.getRow();
fireTableStructureChanged();
}catch(SQLException e) {
JOptionPane.showMessageDialog(null, "Erro ao executar comando!!", "Erro", JOptionPane.PLAIN_MESSAGE);
}
}
Só lembrando que o código é uma tentativa de adaptação (ERRO!).
Mas isso só acontece quando eu tento colocar na table, quando fazia aparecer no System.out ele funcionava.
O problema desse código postado é que o Jack Estripador passou antes e só estou vendo partes.
1 - Qual a relação entre o método
public int getColumnCount() {
try {
return(mdt.getColumnCount()); //exatamente aqui a exceção!
}catch(SQLException e) {
JOptionPane.showMessageDialog(null, "Erro ao retornar o número de colunas!!", "Erro!", JOptionPane.PLAIN_MESSAGE);
}
return(0);
}
e o método
public void executeQuery(String Query) {
try {
con.rowSet.setCommand(Query); //seta o comando no rowset
con.rowSet.execute();
mdt = con.rowSet.getMetaData(); //aqui ele pega o metadata
con.rowSet.last();
nor = con.rowSet.getRow();
fireTableStructureChanged();
}catch(SQLException e) {
JOptionPane.showMessageDialog(null, "Erro ao executar comando!!", "Erro", JOptionPane.PLAIN_MESSAGE);
}
}
?
Não vejo uma ligação entre eles, nem sei em que ordem são executados, nem sei se estão na mesma classe…
Exatamente esse o ponto. Também não vejo ligação entre eles. Porém, julgo que quando eu executo o código e ele tenta colocar os dados na table ele passa por getColumnCount e gera a exceção.
Perdoe-me a falta de código, mas coloquei a parte que imaginei ser importante.
Pacote de conexão - Conecta e desconecta com o banco.
package Conexao;
import com.sun.rowset.JdbcRowSetImpl;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.rowset.JdbcRowSet;
import javax.swing.JOptionPane;
public class Conexao {
public JdbcRowSet rowSet = new JdbcRowSetImpl();
Properties properties = new Properties();
FileInputStream arquivoDePropriedades = null;
public Conexao() {
}
public void getConexao() {
try {
arquivoDePropriedades = new FileInputStream("conexao.properties");
properties.load(arquivoDePropriedades);
try {
rowSet.setUrl(properties.getProperty("jdbc.url"));
rowSet.setUsername(properties.getProperty("jdbc.usuario"));
rowSet.setPassword(properties.getProperty("jdbc.senha"));
}catch(SQLException e) {
JOptionPane.showMessageDialog(null,"Erro de execução em comandos SQL!");
}
}catch(FileNotFoundException e) {
JOptionPane.showMessageDialog(null,"O arquivo de properiedades não foi encontrado!!");
}catch(IOException e) {
JOptionPane.showMessageDialog(null,"Erro ao carregar arquivo!!");
}
}
public void closeConexao() {
try {
rowSet.close();
}catch(Exception e) {
JOptionPane.showMessageDialog(null,"Erro ao fechar objetos de controle de SQL!");
}
}
}
Pacote de Visualização - Cria a table e seta o comando SQL.
package Layout;
import Conexao.Conexao;
import javax.swing.JTable;
public class Table {
ResultSetTableModel modelo = new ResultSetTableModel();
JTable table;
public Table() {
table = new JTable(modelo);
}
public void setQuery(String Query) {
Conexao con = new Conexao();
con.getConexao();
modelo.executeQuery(Query);
con.closeConexao();
}
}
Pacote de visualização - cria o tableModel da table.
package Layout;
import Conexao.Conexao;
import java.sql.*;
import javax.swing.JOptionPane;
import javax.swing.table.AbstractTableModel;
public class ResultSetTableModel extends AbstractTableModel {
ResultSetMetaData mdt;
Conexao con = new Conexao();
private int nor;
@Override
public int getRowCount() {
return(nor);
}
@Override
public int getColumnCount() {
try {
return(mdt.getColumnCount());
}catch(SQLException e) {
JOptionPane.showMessageDialog(null, "Erro ao retornar o número de colunas!!", "Erro!", JOptionPane.PLAIN_MESSAGE);
}
return(0);
}
@Override
public Object getValueAt(int row, int column) {
try {
con.rowSet.absolute(row+1);
return(con.rowSet.getObject(column+1));
}catch(SQLException e) {
JOptionPane.showMessageDialog(null, "Erro ao receber valor nas linha específica!!", "Erro!", JOptionPane.PLAIN_MESSAGE);
}
return("");
}
public void executeQuery(String Query) {
try {
con.rowSet.setCommand(Query);
con.rowSet.execute();
mdt = con.rowSet.getMetaData();
con.rowSet.last();
nor = con.rowSet.getRow();
fireTableStructureChanged();
}catch(SQLException e) {
JOptionPane.showMessageDialog(null, "Erro ao executar comando!!", "Erro", JOptionPane.PLAIN_MESSAGE);
}
}
}
Espero que entenda o código, mas acho que está com muitos erros!
Pra que o resultado do método @Override
public int getColumnCount() {
try {
return(mdt.getColumnCount());
}catch(SQLException e) {
JOptionPane.showMessageDialog(null, "Erro ao retornar o número de colunas!!", "Erro!", JOptionPane.PLAIN_MESSAGE);
}
return(0);
}
seja válido (ou seja, mdt != null, você precisa ter executado o método
public void executeQuery(String Query) {
try {
con.rowSet.setCommand(Query);
con.rowSet.execute();
mdt = con.rowSet.getMetaData();
con.rowSet.last();
nor = con.rowSet.getRow();
fireTableStructureChanged();
}catch(SQLException e) {
JOptionPane.showMessageDialog(null, "Erro ao executar comando!!", "Erro", JOptionPane.PLAIN_MESSAGE);
}
}
Qualquer outra maneira irá apresentar a exceção que originou este tópico.
Outra coisa, a abordagem de colocar consulta SQL na TableModel, no meu entender, é mais que tosca, é ruim, porca e desaconselhável.
Pesquise pelo pattern DAO.
Sim. Realmente, depois de alguns System.out, descobri que o getColumnCount está sendo executado antes do executeQuery.
Agora vou descobrir em que ordem está sendo executado cada método e tentar resolver.
Muito Obrigado!
:roll: