尝试在匿名内部类中访问try-with-resource资源时抛出异常

时间:2015-01-14 13:26:41

标签: java swing jtable defaulttablemodel try-with-resources

正在处理一个项目,其中使用数据库中的数据填充表格。我正在使用try-with-resources语句,因为我希望在离开Connection语句后关闭StatementResultSettry-with-resources个对象。  在我的try块中,我声明了一个JTable对象,它使用一个匿名内部类,用数据库中的数据填充表。

问题:从匿名内部类中的任何方法获取java.sql.SQLException: Operation not allowed after ResultSet closed,尝试访问try-with-resources括号内的资源。

问题:我需要做什么或改变什么才能让我的资源可以被try-with-resources语句中的匿名内部类访问

public class School extends JFrame{
private JTable mytable;
String url="jdbc:mysql://localhost:3306/students";//am connecting to the students database
String username="";
String password="";
public School(){
   super("computer science students");

try(Connection con=DriverManager.getConnection(url, username,password);
Statement smt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
ResultSet rst=smt.executeQuery("select * from students.studentstable")){

   final ResultSetMetaData metadata=rst.getMetaData();
   mytable=new JTable(new DefaultTableModel(){
     @Override
     public int getRowCount(){
       try{
         rst.last();
       return rst.getRow();
       }catch(SQLException sqlex){
          System.out.println(sqlex);
          return 0;
       }
     }
     @Override
     public int getColumnCount(){
         try{
         return metadata.getColumnCount();
         }catch(SQLException sqlex){
          System.out.println(sqlex);
          return 0;
       }
     }
     @Override
     public Class getColumnClass(int col){
        try{
            String classname=metadata.getColumnClassName(col+1);
           return Class.forName(classname);
        }catch(SQLException |ClassNotFoundException sqlex){
          System.out.println(sqlex.getMessage());
          return Object.class;
       }
     }
     @Override
     public String getColumnName(int col){
         try{
             String name=metadata.getColumnName(col+1);
             return name;
         }catch(SQLException sqlex){
          System.out.println(sqlex.getErrorCode());
          return "";
       }
     }

       @Override
     public Object getValueAt(int row,int col){
         try{
        rst.absolute(row+1);
        return rst.getObject(col+1);
         }catch(SQLException sqlex){
             System.out.println(sqlex.getErrorCode());
             return "";
         }
     }  
   });
   JScrollPane pane=new JScrollPane(mytable);
   add(pane);
}catch(SQLException sqlexc){
   System.out.println(sqlexc);
} 
}
public static void main(String[] args) {
  School frame=new School();
  frame.setVisible(true);
    frame.setSize(400,400);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

}

2 个答案:

答案 0 :(得分:3)

问题是,在您离开try-with-resources块之后,您的模型的方法被执行(可能很长)。因此,您的连接此时已关闭,而模型对象的方法仍然引用已关闭连接的ResultSet-Object(因为它隐式最终)。

目前的工作流程如下:

  1. Connection is opend
  2. 创建ResultSet对象
  3. 创建匿名模型对象m
  4. 创建表t并引用模型m
  5. Connection和ResultSet已关闭
  6. [也许是其他行动]
  7. 表t使用模型的方法计算rowcount,values,....
  8. 在第7步中,模型的方法尝试使用ResultSet对象r来获取信息。这会导致您的例外情况。

    为了使其工作,你必须在连接关闭之前提取必要的信息(rowcount,values)并将结果传递给模型的方法(通过使用final对象进行mabye)或在模型的方法中重新打开连接当需要信息时(延迟加载值)。

    编辑:树 - >表(名称正确的数据结构)

答案 1 :(得分:-1)

我认为,为了从匿名内部类访问字段,必须将其声明为final字段。尝试将变量从资源块中取出,将它们声明为final,然后在最后手动关闭它们。