【问题标题】:Parameter index out of range (4 > number of parameters, which is 2)参数索引超出范围(4 > 参数个数,即 2)
【发布时间】:2020-02-21 21:17:52
【问题描述】:

我正在制作一个简单的 java jdbc 程序,我必须在表中插入用户历史记录,但在那里有存货。这是我的代码

public void insertIntoHistory(ArrayList<QuestionAnswer> questionAnswer) throws Exception {
    try {
        conn.setAutoCommit(false);
        int maxId = getMaxSets() + 1;

        for (QuestionAnswer qa : questionAnswer) {
            String getSql = "INSERT INTO userhist(id, questionid, "
                    + "givenanswerid, isCorrect, questionSet) "
                    + "VALUES (NULL,?,?,?,?)";

            pst = conn.prepareStatement(getSql);
            pst.setInt(1, qa.getQuestionId());
            pst.setInt(2, qa.getAnswerId());
            pst.setBoolean(3, (isCorrect(qa.getQuestionId(), qa.getAnswerId())));
            pst.setInt(4, maxId);

            pst.executeUpdate();
        }

        conn.commit();
    } catch (SQLException e) {
        System.out.println(e.getMessage());
        conn.rollback();
        throw e;
    }
}

错误是:

参数索引超出范围(4>参数个数,即0)。 java.sql.SQLException: 参数索引超出范围 (4 > number of 参数,为 0)。在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074) 在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:988) 在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:974) 在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:919) 在 com.mysql.jdbc.PreparedStatement.checkBounds(PreparedStatement.java:3813) 在 com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3795) 在 com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3840) 在 com.mysql.jdbc.PreparedStatement.setInt(PreparedStatement.java:3784) 在 HistoryController.insertIntoHistory(HistoryController.java:37) 在 MultipleChoiseQuestion.jButton2ActionPerformed(MultipleChoiseQuestion.java:223) 在 MultipleChoiseQuestion.access 700 美元(MultipleChoiseQuestion.java:20) 在 MultipleChoiseQuestion$7.actionPerformed(MultipleChoiseQuestion.java:141) 在 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:6533) 在 javax.swing.JComponent.processMouseEvent(JComponent.java:3324) 在 java.awt.Component.processEvent(Component.java:6298) 在 java.awt.Container.processEvent(Container.java:2237) 在 java.awt.Component.dispatchEventImpl(Component.java:4889) 在 java.awt.Container.dispatchEventImpl(Container.java:2295) 在 java.awt.Component.dispatchEvent(Component.java:4711) 在 java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4889) 在 java.awt.LightweightDispatcher.processMouseEvent(Container.java:4526) 在 java.awt.LightweightDispatcher.dispatchEvent(Container.java:4467) 在 java.awt.Container.dispatchEventImpl(Container.java:2281) 在 java.awt.Component.dispatchEvent(Component.java:4711) 在 java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758) 在 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:80) 在 java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:90) 在 java.awt.EventQueue$4.run(EventQueue.java:731) 在 java.awt.EventQueue$4.run(EventQueue.java:729) 在 java.security.AccessController.doPrivileged(Native Method) 在 java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80) 在 java.awt.EventQueue.dispatchEvent(EventQueue.java:728) 在 java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) 在 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) 构建成功(总时间:6 秒)

我认为问题来自这种方法

private boolean isCorrect(int questionId, int ansId) throws SQLException {
    String sql = "SELECT COUNT(*) AS Total FROM correctanswer where questionid = ? and answerid = ?";
    boolean isCorrect = false;

    try {
        pst = conn.prepareStatement(sql);
        pst.setInt(1, questionId);
        pst.setInt(2, ansId);

        ResultSet res = pst.executeQuery();
        int count = 0;
        if (res.next()) {
            count = res.getInt(1);
        }

        isCorrect = count > 1;

    } catch (SQLException e) {
        System.out.println(e.getMessage());
        throw e;
    }

    return isCorrect;
}

这是我的表结构

这里发生了什么,请帮助我

【问题讨论】:

  • @Yserbius 那没有解决我的问题请你看看它
  • 可能我们有这种奇怪的行为,因为普遍不清楚。 1. 请在循环之前创建一次准备好的语句,然后在循环中进行设置和执行。您还必须在执行后关闭语句(考虑try (...) {....})。 2. 还有一个问题,你确定异常来自这个方法而不是来自getMaxSets() 吗?
  • 您使用的是什么数据库?您也可以发布您的架构吗?
  • 看起来pst 是一个字段,您可能会通过同时访问同一个对象来覆盖它。您通常应该尝试保留对方法的 JDBC 类型局部变量的引用,否则您必须确保使用唯一字段,或正确同步访问。但是,为了确保我们需要看到minimal reproducible example

标签: java mysql sql jdbc


【解决方案1】:

问题可能源于您尝试将NULL 插入id 列。由于它是自动增量非空,因此您应该假装它不存在以用于INSERT 命令。

【讨论】:

  • 我通过在 isCorrect 方法中创建 PrepareStatement 的新实例解决了这个问题。感谢您的回复
猜你喜欢
  • 2022-01-04
  • 2018-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-18
  • 1970-01-01
  • 1970-01-01
  • 2020-02-16
相关资源
最近更新 更多