【问题标题】:Convert ArrayList to mysql insert parameters in Java在Java中将ArrayList转换为mysql插入参数
【发布时间】:2015-09-30 21:54:56
【问题描述】:

我被困住了。我拒绝长时间停留,所以我寻求帮助。我想要做的是将我从另一个数据库的 select 语句中检索的 ResultSet 放入 ArrayList 中,然后将数组列表转换为 Java 中的插入准备语句。

** 更新 ** 问题是我收到“java.sql.SQLException:参数索引超出范围(6 > 参数数量,即 5)”。这意味着它正在接收 6 个参数而不是 5 个,我看不出这是如何发生的。由于在调试器中我正在观察值是否正确更新,但我的逻辑现在不正确。

我运行调试器,发现我只是将所有值转储到第一个参数中。我明白我需要做什么。这是将 ArrayList 结果拆分为插入语句的每个参数。我的大脑已经死了。这是一天的结束,这是我拼图的最后一块,所以我可以继续前进。我只是不知道该怎么做。感谢您的帮助!

这就是我的结果 ArrayList 所持有的。

[800-0022-08, 0025, 2015-09-30, 600040, 115]
[800-0022-08, 0024, 2015-09-30, 600040, 115]
[800-0022-08, 0008, 2015-09-30, 600040, 115]
[800-0022-08, 0036, 2015-09-30, 600040, 115]
[800-0022-08, 0035, 2015-09-30, 600040, 115]
[800-0022-08, 0034, 2015-09-30, 600040, 115]

代码如下。

    ResultSet rs = (ResultSet) stmt.executeQuery(query);
                ResultSetMetaData rsmd = (ResultSetMetaData) rs.getMetaData();
                int numberOfColumns = rsmd.getColumnCount();
                int rowCount = 1

                ArrayList <String[]> result = new ArrayList<>();

                while (rs.next()) {
                    System.out.println("Row " + rowCount + ":  ");
                    String[] row = new String[numberOfColumns];

                    for (i = 1; i < numberOfColumns + 1; i++) {
                        System.out.print("   Column " + i + ":  ");
                        System.out.println(rs.getString(i);
                        row[i - 1] = rs.getString(i);
                    }
                    result.add(row);

                    System.out.println("");
                    rowCount++;             
                }

                String Connection   = "CONNECTIONSTRING";
                String UserName     = "USERNAME";
                String Password     = "PASSWORD";

                String MySQLQuery = "INSERT INTO serial (MTSER_CODE, MTSER_SERIAL, MTSER_RECDATE, MTSER_WO, MTSER_WOSUF)" + "VALUES (?,?,?,?,?)";

    String Driver = "org.gjt.mm.mysql.Driver";
                    Class.forName(Driver);

                    java.sql.Connection MyConnection = (java.sql.Connection) DriverManager.getConnection(Connection, UserName, Password);

                    java.sql.PreparedStatement preparedStmt;
                    preparedStmt = MyConnection.prepareStatement(MySQLQuery);



// ** UPDATED FOR LOOP **
                    for (String[] arr : result) {
                try (java.sql.PreparedStatement preparedStmt = MyConnection.prepareStatement(MySQLQuery)) {
                    for (int q = 0; q < arr.length; q++) {
                        preparedStmt.setString(q + 1, arr[0]);
                        preparedStmt.setString(q + 2, arr[1]);
                        preparedStmt.setString(q + 3, arr[2]);
                        preparedStmt.setString(q + 4, arr[3]);
                        preparedStmt.setString(q + 5, arr[4]);
                    }
                    preparedStmt.execute();

                } catch (SQLException e) {
                    e.printStackTrace();
                }

            }

迭代后的插入语句如下所示:INSERT INTO serial (MTSER_CODE, MTSER_SERIAL, MTSER_RECDATE, MTSER_WO, MTSER_WOSUF)" + "VALUES ([800-0022-08, 0025, 2015-09-30, 600040, 115],** Not Specified **,** Not Specified **,** Not Specified **,** Not Specified **)

【问题讨论】:

  • 我没有阅读所有内容,但 for(int p = 1; p &lt; result.size(); p++) 看起来很可疑:您的意思是不是 for(int p = 0 ; p &lt; result.size(); p++)(然后在 setString 中使用 p+1)?
  • 尝试将preparedStmt.executeUpdate(); 语句放在循环之外,看看是否有帮助。就像现在一样,您在设置所有参数之前执行PreparedStatement,因此出现异常
  • Titus 我将您的建议添加到代码中,但现在它抛出此错误。 “java.sql.SQLException: 参数索引超出范围(6 > 参数个数,即 5)。”

标签: java sql jdbc insert


【解决方案1】:

这样的批量插入应该使用批处理,确保批处理不会太大。

您还应该确保清理您的资源。

try (Connection conn = DriverManager.getConnection(url, userName, password);
     PreparedStatement stmt = conn.prepareStatement(sql)) {
    int rowCount = 0;
    for (String[] row : result) {
        for (int i = 0; i < 5; i++) // hardcoded 5 since SQL has 5 markers
            stmt.setString(i + 1, row[i]);
        stmt.addBatch();
        if (++rowCount % 1000 == 0)
            stmt.executeBatch();
    }
    if (rowCount % 1000 != 0)
        stmt.executeBatch(); // execute last batch
}

【讨论】:

  • 安德烈亚斯。我将把它包含在我的最终代码中,因为我相信这会很有帮助!
  • 你的论点很有说服力。我确实添加了批处理,所以我更改了接受的答案。
【解决方案2】:

你的问题在这里:

for (int q = 0; q < arr.length; q++) {
    preparedStmt.setString(q + 1, arr[0]);
    preparedStmt.setString(q + 2, arr[1]);
    preparedStmt.setString(q + 3, arr[2]);
    preparedStmt.setString(q + 4, arr[3]);
    preparedStmt.setString(q + 5, arr[4]);
}

您正在循环 - 如果数组大小为 5,则在最后一次迭代中 q = 4,因此您设置为 q + 5,即 9

要么不循环:

preparedStmt.setString(1, arr[0]);
preparedStmt.setString(2, arr[1]);
preparedStmt.setString(3, arr[2]);
preparedStmt.setString(4, arr[3]);
preparedStmt.setString(5, arr[4]);

或循环一次调用setString 每次迭代:

for (int q = 0; q < arr.length; q++) {
    preparedStmt.setString(q + 1, arr[q]);
}

【讨论】:

  • 您非常好心地指出了逻辑错误。我希望我也能给你正确的答案选择,因为你在我实施了 Titus 的建议之后回答了这个问题。我应该刚回家睡觉。我从这个问题中学到了很多,并将在我的问题中发布最终代码供其他人查看。
【解决方案3】:

试试这样的:

for (String[] arr : result) {
    try (PreparedStatement preparedStmt = MyConnection.prepareStatement(MySQLQuery);) {
        for (int i = 0; i < arr.length; i++) {
            preparedStmt.setString(i + 1, arr[i]);
        }
        preparedStmt.execute();
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

这样做是为result 列表中的每个String 数组创建一个新的PreparedStatement,并使用数组中的值设置此语句的值。

【讨论】:

  • 你应该提到result.get(p)返回一个字符串数组,表示查询中每一列的值,并将该数组转换为一个字符串将导致上述奇怪的 SQL 查询。
  • 准备语句 inside 循环是完全错误的,可能不是你的意思,因为代码甚至不会在 try-with- 之外使用 execute() 编译资源块。
  • 所以我在上面的代码中添加了这个建议。在 try 语句中包含preparedStmt,因为我知道这在外面是行不通的。感谢安德烈亚斯确认这一点。现在我收到“java.sql.SQLException:参数索引超出范围(6 > 参数数量,即 5)”。错误。我感觉这与我的 for 循环迭代量有关。
猜你喜欢
  • 2012-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
相关资源
最近更新 更多