【问题标题】:Java program throwing exception while executingbatchJava程序在执行批处理时抛出异常
【发布时间】:2012-11-12 09:47:15
【问题描述】:

我正在实现一个 JAVA 应用程序,它从不同的 URL 获取数据并将这些数据存储到数据库中。每个表都有它自己的 URL 集合,它从中接收数据。我这样做是通过为每个表实现一个preparedstatement,从URL 获取数据,将数据绑定到preparestatement 并将数据作为批处理添加,直到一个表的所有URL 都完成。然后在prepare语句上执行executeBatch。我确实有一些 6-8 表,每个表有大约 200 行。我对每个表都执行相同的过程,但是在更新 3-4 个表之后,我的 executeBacth 抛出了一个异常,上面写着:

 java.sql.SQLException: SQL Exception : [Microsoft][ODBC Driver
 Manager] Invalid string or buffer length   at
 sun.jdbc.odbc.JdbcOdbcPreparedStatement.setObject(JdbcOdbcPreparedStatement.java:1438)
    at
 sun.jdbc.odbc.JdbcOdbcPreparedStatement.setObject(JdbcOdbcPreparedStatement.java:1073)
    at
 sun.jdbc.odbc.JdbcOdbcPreparedStatement.emulateExecuteBatch(JdbcOdbcPreparedStatement.jjva:2104)
    at
 sun.jdbc.odbc.JdbcOdbcPreparedStatement.executeBatchUpdate(JdbcOdbcPreparedStatement.java:1782)
    at
 sun.jdbc.odbc.JdbcOdbcStatement.executeBatch(JdbcOdbcStatement.java:911)
    at FaoClient.CFaoTable.InsertFromPartialSource(CFaoTable.java:174)

我通过更改获取表数据的顺序测试了相同的程序,但在插入数据 4-5 个表后总是抛出异常。我觉得这就像一些内存泄漏情况,但我知道 JAVA 抓取收集器永远不会让这种情况发生。我对这个 JAVA 世界很陌生,所以我可能错了。我正在粘贴我的代码部分,它使用 java.sql.* 来插入记录。

  private boolean BindValueToStmt(PreparedStatement ps, int index, TableCol.ColType type, String ColVal) {
        if ((ps == null) || (ColVal == "")) {
            return false;
        }
        try {
            switch (type) {
                case INTEGERT: {
                    ps.setInt(index, Integer.parseInt(ColVal));
                    return true;
                }
                case STRINGT: {
                    ps.setString(index, ColVal);
                    return true;
                }
                case REALT: {
                    ps.setFloat(index, Float.parseFloat(ColVal));
                    return true;
                }
                case DOUBLET: {
                    ps.setDouble(index, Double.parseDouble(ColVal));
                    return true;
                }
                default:
                    ps.setNull(index, java.sql.Types.NULL);
            }
            return true;
        } catch (SQLException E) {
            System.out.println("Error in Setting the value of the col in table: " + Name + E);
            E.printStackTrace();
            return false;
        }
    }



   private String CreatePreparedInsertStatement() {
        StringBuilder insertStmt = new StringBuilder("insert into " + Name + "(");
        String val = " values (";
        for (int index = 0; index < Columns.size(); index++) {
            TableCol col = Columns.get(index);
            if (index != Columns.size() - 1) {
                String Stmt = col.GetColName() + ", ";
                insertStmt.append(Stmt);
                val += "?, ";
            } else {
                String Stmt = col.GetColName() + ")";
                insertStmt.append(Stmt);
                val += "?)";
            }
        }
        insertStmt.append(val);
        return insertStmt.toString();
    }

下面是实际插入数据的代码。

  private boolean InsertFromPartialSource(Connection conn, SAXReader reader) {
        try {
            if (conn == null || reader == null) {
                return false;
            }
           //Some Code not realted to java.sql

            conn.setAutoCommit(false);
            String strPs= CreatePreparedInsertStatement();
            PreparedStatement ps = conn.prepareStatement(strPs);

            //Some Code not realted to java.sql

            for (int index = 0; index < Columns.size(); index++) {
                    TableCol col = Columns.get(index);
                    //Some Code not realted to java.sql
                    if (!BindValueToStmt(ps, index + 1, col.GetColType(), colVal)) {
                        ps.setNull(index + 1, TableCol.GetSqlColTypeFrmType(col.GetColType()));
                    }
                }
                rowCount++;
                System.out.println(rowCount + "rows has been extracted for table \" " + Name);
                ps.addBatch();

            }
            if (rowCount > 0) {
                int RecordsUpdated[] = ps.executeBatch();
            }
            conn.commit();
            conn.setAutoCommit(true);
            ps.close();
            return true;
}

为了清楚起见,我只粘贴了与数据库更新相关的函数 InsertFromPartialSource 的一部分。有人可以指出这里出了什么问题吗?

上述问题的解决方法是: 将您的 MySql 连接器或驱动程序更改为 MySqlJDBC 驱动程序。有可能 在以下链接中找到: http://dev.mysql.com/downloads/connector/j/5.1.html

【问题讨论】:

  • 在 'BindValueToStmt' 的 catch 块中,你真的应该重新抛出 SQL 异常,而不仅仅是捕获它并返回 false...
  • CFaoTable.java:174 是哪一行?
  • @auselen int RecordsUpdated[] = ps.executeBatch();
  • 考虑为您的数据库切换到真正的 JDBC 驱动程序(如果有的话)。 JdbcOdbc 桥相当糟糕,特定的 JDBC 驱动程序通常工作得更好
  • @Manish:如果出现 SQL 异常,进一步处理相应的行没有任何意义。仔细查看您的执行路径 - 在发生 SQL 异常后继续进行是没有意义的(它甚至可能是您在问题中描述的问题的根本原因。

标签: java jdbc


【解决方案1】:

考虑为您的数据库切换到真正的 JDBC 驱动程序(如果有的话)。 JdbcOdbc 桥相当糟糕,特定的 JDBC 驱动程序通常工作得更好。

【讨论】:

    【解决方案2】:

    您可以尝试执行,而不是执行批处理,以避免蹩脚的批处理操作。

    【讨论】:

    • 您好,但是当您插入大量记录时,对每条记录执行插入查询会非常低效。
    猜你喜欢
    • 2011-12-12
    • 2019-07-19
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 2012-03-30
    • 1970-01-01
    • 2012-03-08
    • 1970-01-01
    相关资源
    最近更新 更多