【问题标题】:IndexOutOfBounds. How should you store data from resultSet into an ArrayList?索引出界。应该如何将 resultSet 中的数据存储到 ArrayList 中?
【发布时间】:2020-03-13 08:15:40
【问题描述】:

所以,我有一个方法(应该)返回一个包含来自 sqlite 数据库的数据的字符串:

public String getLesson() throws ClassNotFoundException {
    ArrayList list = new ArrayList();

    int selectedColumn = tblOpenLesson.getSelectedColumn();
    int selectedRow = tblOpenLesson.getSelectedRow();
    String name = (String) tblOpenLesson.getModel().getValueAt(selectedRow, selectedColumn);

    try {
        Class.forName("org.sqlite.JDBC");
        Connection con = DriverManager.getConnection("jdbc:sqlite:sql_items.sqlite");
        Statement stmtGetLesson = con.createStatement();
        ResultSet rs = stmtGetLesson.executeQuery("SELECT * FROM lessons WHERE lesson_id  = '" + name + "';");

        if (rs.next()) {
            list.add(rs.getString("lesson"));
        }
    } catch (SQLException e) {
        JOptionPane.showMessageDialog(null, e);
    } catch (ClassNotFoundException ex) {
        Logger.getLogger(openLesson.class.getName()).log(Level.SEVERE, null, ex);
    }

    return (String) list.get(0);
}

我会使用该字符串来定位一个文本文件,通过该文本文件,其内容将显示在来自另一个类的 JTextPane 上

private void btnOpenLessonPopUpActionPerformed(java.awt.event.ActionEvent evt) {                                                   

    try {
        FileReader fr = new FileReader("Lessons\\" + getLesson() + ".txt"); //this is Line 126

        try (BufferedReader br = new BufferedReader(fr)) {
            mainScreen.lessonPane.read(br, null); //  lessonPane is from another class
            br.close();
        } catch (IOException e) {
            System.out.println(e);
            this.setVisible(false);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(openLesson.class.getName()).log(Level.SEVERE, null, ex);
        }  
    } 

但是我得到了这个错误:

线程“AWT-EventQueue-0”中的异常 java.lang.IndexOutOfBoundsException:索引:0,大小:0 在 java.util.ArrayList.rangeCheck(ArrayList.java:657) 在 java.util.ArrayList.get(ArrayList.java:433) 在 mainWindow.openLesson.getLesson(openLesson.java:204) 在 mainWindow.openLesson.btnOpenLessonPopUpActionPerformed(openLesson.java:126) 在 mainWindow.openLesson.access$000(openLesson.java:19) 在 mainWindow.openLesson$1.actionPerformed(openLesson.java:60) 在 javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022) 在 javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348) 在 javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) 在 javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) 在 javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) 在 java.awt.Component.processMouseEvent(Component.java:6539) 在 javax.swing.JComponent.processMouseEvent(JComponent.java:3324) 在 java.awt.Component.processEvent(Component.java:6304) 在 java.awt.Container.processEvent(Container.java:2239) 在 java.awt.Component.dispatchEventImpl(Component.java:4889) 在 java.awt.Container.dispatchEventImpl(Container.java:2297) 在 java.awt.Component.dispatchEvent(Component.java:4711) 在 java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4904) 在 java.awt.LightweightDispatcher.processMouseEvent(Container.java:4535) 在 java.awt.LightweightDispatcher.dispatchEvent(Container.java:4476) 在 java.awt.Container.dispatchEventImpl(Container.java:2283) 在 java.awt.Window.dispatchEventImpl(Window.java:2746) 在 java.awt.Component.dispatchEvent(Component.java:4711) 在 java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760) 在 java.awt.EventQueue.access$500(EventQueue.java:97) 在 java.awt.EventQueue$3.run(EventQueue.java:709) 在 java.awt.EventQueue$3.run(EventQueue.java:703) 在 java.security.AccessController.doPrivileged(Native Method) 在 java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74) 在 java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:84) 在 java.awt.EventQueue$4.run(EventQueue.java:733) 在 java.awt.EventQueue$4.run(EventQueue.java:731) 在 java.security.AccessController.doPrivileged(Native Method) 在 java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74) 在 java.awt.EventQueue.dispatchEvent(EventQueue.java:730) 在 java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205) 在 java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) 在 java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) 在 java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) 在 java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) 在 java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

我想我不知道为什么会这样。我还是编程新手。

【问题讨论】:

  • 如果你只想要一列那么不要做SELECT * FROM lessons,只要select column
  • 这不是错误,但您不应该将 ArrayList 用作变量的类型(在左侧),因为它是一个具体的类而不是接口。您应该改用 List 。此外,此列表仅包含字符串,因此应进一步限制泛型 (<>)。所以,ArrayList list = new ArrayList(); 应该是 List<String> list = new ArrayList<>;

标签: java sqlite arraylist jdbc resultset


【解决方案1】:

如果 sql 查询没有返回任何行,最后一行将抛出异常,因为您的列表为空。

 return (String) list.get(0);

所以要么改成

if (!list.isEmpty() {
    return (String) list.get(0);
}
return null; //If list is empty

甚至更好,因为您只对第一行感兴趣,您可以跳过列表并替换

if (rs.next()) {
    list.add(rs.getString("lesson"));
}

与

if (rs.next()) {
    return rs.getString("lesson");
}

你仍然需要在方法结束时返回

return null;

比你这样使用它

try {
    String lesson = getLesson();
    if (lesson != null) {
         //open file...
    }
...

【讨论】:

  • 看在皮特的份上,请使用 PreparedStatement 确保您的 SQL 安全 - 与 OP 交谈,而不是与 Joakim 交谈
  • 我试过了。它现在给我 java.io.FileNotFoundException: Lessons\.txt (系统找不到指定的文件)。我认为这是因为最后一个 return 语句不包含任何内容,这就是该方法所得到的。我也尝试将它放在字符串上,但它返回 null: java.io.FileNotFoundException: Lessons\null.txt (系统找不到指定的文件)
  • 如果你打算使用ArrayList,也使用ArrayList<String> list = ..; 在大多数情况下,如果你看到演员表,那么你的代码有问题。
  • 那是因为您的查询没有返回任何内容。检查数据库是否实际包含数据,并确认您在应用程序中的查询返回您期望的数据
  • @itskenleton 您不应该一次问几个问题,但由于该方法可能不会返回任何内容(空字符串),您当然必须在继续之前检查结果。在这种情况下,如果方法返回 null 而不是空字符串可能会更好。答案已更新
【解决方案2】:

在不知道数据结构的情况下很难说,但是,从您的查询中:"SELECT * FROM lessons WHERE lesson_id = '" + name + "';" 似乎您正在尝试将lesson_id 与您正在学习的课程的name 匹配。

也可能是String name = (String) tblOpenLesson.getModel().getValueAt(selectedRow, selectedColumn); 没有给你所期望的。

另一方面,您确实需要查看Prepared Statements。照原样,您的应用程序很容易受到 SQL 注入。

就个人而言,我也会重构代码,以便:

if (rs.next()) {
    list.add(rs.getString("lesson"));
}

变成:

if (rs.next()) {
    return rs.getString("lesson");
}

而这个:return (String) list.get(0); 变为 return "";。

【讨论】:

  • 这解决了这两个问题。当我移动 return 语句时,IndexOutOfBounds 已修复。还有 String name = (String) tblOpenLesson.getModel().getValueAt(selectedRow, selectedColumn);正在从错误的列/行中获取数据。非常感谢!
  • @itskenleton:不客气。请确保您在代码中解决了 SQL 注入问题。
  • 是的。感谢您的建议,我对 SQL 注入等一无所知。很高兴知道。
【解决方案3】:

您在尝试检索索引 0 处的值时抛出了 IndexOutOfBounds 异常。这意味着您的 ArrayList 中没有添加任何内容。调用 next() 时,您的数据很可能不是有效行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-24
    • 2016-08-17
    • 1970-01-01
    • 2010-10-13
    • 2017-06-06
    相关资源
    最近更新 更多