我一直在尝试修复我的代码的一部分

java.sql.SQLException: Parameter index out of range (2 > number of parameters, which is 1).


我已经搜索了stackoverflow和Internet的其他部分,但找不到解决方案,该错误已得到纠正。

这是类文件的开始:

PreparedStatement stmt;


这是我的构造函数:

public DataAccessObjectImpl() throws Exception {
    this.conn = new DBConnector();
}


这是导致问题的方法:

@Override
public boolean addAlbum(int UID, String artist, String album) {
    String sql = "";

    try {
        stmt = conn.getConnection().prepareStatement("INSERT INTO music (identifier, UID, artist, album) VALUES (?,?,?,?);");
        stmt.setString(1, getNewIdentifier());
        stmt.setInt(2, UID);
        stmt.setString(3, artist);
        stmt.setString(4, album);
        stmt.executeUpdate();
    } catch (Exception ex) {
        System.out.println("nugget 1 : " + ex);
    } finally {
        try {
            if (stmt != null) {
                stmt.close();
                return true;
            }
        } catch (Exception e) {
            System.out.println("Nugget 2 : " + e);
        }
    }
return false;
}


(“金块”一词很容易让自己在日志/控制台中找到)

从我可以在stackoverflow上收集到的信息来看,它可能是我的问题,这就是问题所在,但我似乎无法弄清楚该怎么做。我将prepareStatement用于在同一个类中工作正常的其他方法。



我在下面提供了一些工作代码,我想用preparestatement替换此代码以修补SQL Injection:

try {
        stmtb = conn.getConnection().createStatement();
            sql = "INSERT INTO music VALUES ('" + getNewIdentifier() + "','" + UID + "','" + artist + "','" + album + "')";
        } catch (SQLException ex) {
        }
        try {
            stmt.executeUpdate(sql);
            return true;
        } catch (Exception e) {
            System.out.println(e);
        }
return false;


谢谢高级!



通过更改此行来修复:

stmt = conn.getConnection().prepareStatement("INSERT INTO music (identifier, UID, artist, album) VALUES (?,?,?,?);");


我将其更改为:

PreparedStatement stmt = conn.getConnection().prepareStatement("SELECT * FROM user WHERE username = (?);");


并删除此行:

PreparedStatement stmt;


谢谢Kayaman的帮助!

最佳答案

由于查询是正确的,但是会发生异常,因此唯一可能的解释是stmt会以某种方式损坏。唯一现实的情况是在多线程环境中,多个线程使用相同的stmt执行查询。

由于您使用prepareStatement()创建新的PreparedStatement对象,因此没有理由共享“全局”引用。在大多数情况下,最佳实践是在尽可能小的范围内定义和使用变量。

因此,从外部作用域中删除stmt变量,而只需编写

PreparedStatement stmt = conn.getConnection().prepareStatement(query);


您需要的地方。

07-26 05:38