在AbstractTableModel中使用ResultSet后,在ResultSet关闭后不允许进行操作

时间:2019-07-05 19:41:48

标签: java resultset tablemodel

我正在尝试创建一个框架,向我显示数据库中所有电影的名称,然后他们在框架中选择一行以执行另一个查询。

我有一个ResultSet(rs),用于接收执行查询以选择电影名称的结果。之后,我在SQLTableModel中使用rs来创建JTable并显示在框架中。该表显示了数据库中所有电影的名称。一切正常。

但是,当我选择一行时,我使用相同的rs来接收另一个查询,该查询在我的数据库中选择了我在JTable中选择的电影的所有信息,并且出现了一些错误。

首先,我在JTable中选择的行丢失了值(电影的名称)。但是在其他行中什么也没有发生。 其次,控制台在函数“ getValueAt”中向我显示了一个来自SQLTableModel的错误,内容为“错误:关闭ResultSet后,错误#0操作”。

我在stackoverflow中搜索了一些解决方案,但没有成功。

我做了一些测试。如果我的ResultSet(rs)在我在SQLTableModel中使用它之前收到多个查询,则一切正常。但是在SQLTableModel中使用它后,如果再次尝试使用它,则会收到我提到的错误。

FrameCliente.java

public class FrameCliente {

    JFrame frameCliente;
    JTable table;

    BancoDeDados bd;
    ResultSet rs;

    public FrameCliente() {
        bd = new BancoDeDados();
        frameCliente = new JFrame();
        table = new JTable();
        rs = bd.listar("SELECT fil_nome Nome FROM filme");
        table.setModel(new SQLTableModel(rs));

        table.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                if(table.getSelectedRowCount() > 0) {
                    rs = bd.listar(" SELECT * FROM filme WHERE fil_nome = '" + table.getValueAt(table.getSelectedRow(), 0) + "'");  
                }
            }
        });

        frameCliente.add(new JScrollPane(table));
        frameCliente.setTitle("Filmes");
        frameCliente.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frameCliente.setSize(800, 300);
        frameCliente.setLocationRelativeTo(null);
        frameCliente.setVisible(true);
    }

}

SQLTableModel.java

public class SQLTableModel extends AbstractTableModel {

    private ResultSet rs;
    private ResultSetMetaData rsmd;
    private int numberOfRows=0;

    public SQLTableModel(ResultSet rs){
        this.rs = rs;
        try { //Todos os métodos são privado e isso gera exceção.
            rsmd = this.rs.getMetaData();
            //Navegar para encontrar a ultima linha, para saber quantas linhas a tabela possui.
            this.rs.last();     // Pega a ultima linha;
            numberOfRows = rs.getRow(); //Devolve a linha, no caso, a ultima.
            this.rs.beforeFirst(); //Retorna para a primeira linha.
        }catch(SQLException sqle){
            System.out.printf("Erro: #%d [%s]\n", 
                    sqle.getErrorCode(), sqle.getMessage());
        }

    }


    @Override
    public int getRowCount() {
        // TODO Auto-generated method stub
        return numberOfRows;
    }

    @Override
    public int getColumnCount() {
        // TODO Auto-generated method stub
        try { 
            return rsmd.getColumnCount();
        }catch(SQLException sqle){
            System.out.printf("Erro: #%d [%s]\n", 
                    sqle.getErrorCode(), sqle.getMessage());
            return 0; // Se der exceção não retorna nenhuma coluna;
        }
    }

    @Override
    public String getColumnName(int column) {
        String ColumnName = "";
        try { 
            ColumnName = rsmd.getColumnLabel(column+1);
        }catch(SQLException sqle){
            System.out.printf("Erro: #%d [%s]\n", 
                    sqle.getErrorCode(), sqle.getMessage());
        }
        return ColumnName;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        // TODO Auto-generated method stub
        Object dado = null;
        try { 
            rs.absolute(rowIndex+1);
            dado = rs.getObject(columnIndex+1);
        }catch(SQLException sqle){
            System.out.printf("Erro: #%d [%s]\n", 
                    sqle.getErrorCode(), sqle.getMessage());
        }
        return dado;
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        String className;
        try { 
            className = rsmd.getColumnClassName(columnIndex+1);
            return Class.forName(className);
        }catch(SQLException sqle){
            System.out.printf("Erro: #%d [%s]\n", 
                    sqle.getErrorCode(), sqle.getMessage());
        } catch (ClassNotFoundException cnfe) {
            System.out.printf("Erro: %s\n", cnfe.getMessage());
        }
        return null;
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }

    public void atualizarTabela() {
        fireTableDataChanged();
    }


}

BancoDeDados

public class BancoDeDados {
    private Connection con = null;
    private Statement sta = null;    //faz consultas
    private ResultSet rset = null;  //armazenas as info pra trabalhar com elas depois - resultado do select

    public BancoDeDados() {
        this.conectar();
    }


    public void conectar() {
        String servidor = "jdbc:mysql://localhost:3306/cinema?useSSL=true&useTimezone=true&serverTimezone=UTC";
        String usuario = "root";
        String senha = "coreduo2";
        String driver = "com.mysql.cj.jdbc.Driver";

        try {

            //Class.forName(driver);
            this.con = DriverManager.getConnection(servidor, usuario, senha);
            this.sta = this.con.createStatement();
        }
        catch(Exception e)
        {
            System.out.println("Error " + e.getMessage());
        }
    }

    public boolean estaConectado() {
        if (con != null) {
            return true;
        }
        else {
            return false;
        }
    }

    public void desconecte() {
        try {
            con.close();
            System.out.println("Conexao com banco encerrado");
        }
        catch(SQLException e) {
            System.out.println("Erro: " +  e.getMessage());
        }
    }

    public ResultSet listar(String query) {
        try {
            return sta.executeQuery(query);
            //this.sta = this.con.createStatement();
            /*while (this.rset.next()) {
                System.out.println("ID: " + rset.getString("fil_codigo") + " Nome: " + rset.getString("fil_nome") + " Duração: " + rset.getString("fil_duracao"));
            }*/

        }
        catch(SQLException e) {
            System.out.println("Erro "+ e.getMessage());
            return null;
        }   
    }

    public void inserir(String query) {
        try {
            this.sta.executeUpdate(query);
        }
        catch(SQLException e) {
            System.out.println("Erro"+ e.getMessage());
        }

    }

    public void excluir(String query) {
        try {
            this.sta.executeUpdate(query);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void editar(String query) {
        try {
            this.sta.executeUpdate(query);
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

}

1 个答案:

答案 0 :(得分:1)

始终使用诸如ArrayList或Map之类的内存结构来缓存从DB获得的结果。由于与数据库的连接很昂贵,因此保持此连接也很昂贵。因此,尽可能快地,尽可能短地调用DB。一旦将数据存储在内存中,您就可以随意操作。