【问题标题】:single PreparedStatement for batch processiong用于批处理的单个 Prepared Statement
【发布时间】:2013-07-23 05:55:54
【问题描述】:

我想在一个表中插入记录,同时我想更新另一个表中的记录。为此,如果任何一个查询失败,我想使用事务,那么所有查询都会回滚。为此,我使用批处理...步骤如下

首先我将AutoCommit(false)设置为连接obj。

然后dmlPreparedStatement = dbConnection.prepareStatement(Insertquery);

  • 设置参数到dmlPreparedStatement
  • dmlPreparedStatement.addBatch();

在此之后,我想为此批量添加 UPDATE 查询-

  • dmlPreparedStatement = dbConnection.prepareStatement(Updatequery); 相同的 PreparedStatement 对象,但具有新的更新查询
  • 设置参数为dmlPreparedStatement
  • dmlPreparedStatement.addBatch();

dmlPreparedStatement.executeBatch(); 完成时只执行更新语句插入操作不完成。

他们是否有任何方式将相同的 PreparedStatement 对象用于多个差异。查询。

尝试块中的代码

String query="INSERT INTO CANDIDATEANSWER " +
                "(CANDIDATEEXAMITEMID,FKCANDIDATEID,FKITEMID,OPTIONID,ATTEMPTEDTIME,ISCORRECT) " +
                "VALUES (?,?,?,?,?,?)";
        dbConnection = icrudCandidate.getConnection();
        dbConnection.setAutoCommit(false);
        dmlPreparedStatement = dbConnection.prepareStatement(query);
        for (CandidateAnswer candidateAnswer : candidateItemAssociation.getCandidateAnswers()) {
            if(candidateAnswer.getOptionID() != 0)
            {
                dmlPreparedStatement.setLong(1, candidateAnswer.getCandidateExamItemID());
                dmlPreparedStatement.setLong(2, candidateAnswer.getFkcandidateID());
                dmlPreparedStatement.setLong(3, candidateAnswer.getFkItemID());
                dmlPreparedStatement.setLong(4, candidateAnswer.getOptionID());
                java.util.Date dt =  new java.util.Date();
                dmlPreparedStatement.setObject(5, dt,java.sql.Types.TIMESTAMP,java.sql.Types.TIMESTAMP);
                String sql = "SELECT ISCORRECT FROM ITEMOPTION IO WHERE IO.OPTIONID="+candidateAnswer.getOptionID();
                preparedStatement = dbConnection.prepareStatement(query);
                resultSet = preparedStatement.executeQuery(sql);
                while(resultSet.next())
                {
                    if(resultSet.getBoolean("ISCORRECT"))
                    {
                        dmlPreparedStatement.setBoolean(6, true);
                    }
                    else
                    {
                        isCorrect=false;
                        dmlPreparedStatement.setBoolean(6, false);
                    }
                }
                resultSet.close();
            }
            dmlPreparedStatement.addBatch();
        }
         query="UPDATE CANDIDATEITEMASSOCIATION SET ISCORRECT=?,MARKSOBTAINED=? WHERE CANDIDATEEXAMITEMID="+candidateItemAssociation.getCandidateAnswers().get(0).getCandidateExamItemID();
         PreparedStatement dmlPreparedStatement1 = dbConnection.prepareStatement(query);
         dmlPreparedStatement1.setBoolean(1, isCorrect);
         if(isCorrect)
         {
             dmlPreparedStatement1.setString(2, String.valueOf(getPerItemMarksByPaperId(paperId)));              
         }
         else
         {               
             dmlPreparedStatement1.setString(2, String.valueOf((getNagetiveMarksPerItemByPaperIdAndEventID(eventID,paperId)*-1)));
         }
         dmlPreparedStatement1.addBatch();

        int[] count = dmlPreparedStatement.executeBatch();
        count = dmlPreparedStatement1.executeBatch();
        dbConnection.commit();
        return true;

【问题讨论】:

    标签: java jdbc prepared-statement batch-processing


    【解决方案1】:

    批处理和事务是两件不同的事情:使用批处理时,如果两者之间出现故障,您不会得到回滚。 批处理的主要优点是它允许您执行具有多个参数的同一指令

    您需要做的是在开始更新之前使用dmlPreparedStatement.executeBatch(); 执行第一个插入批处理。

    更新批处理执行完毕后,您需要使用connection.commit(); 提交事务,或者如果失败则回滚。

    更多信息在example

    【讨论】:

    • 谢谢,链接很有用,但是有了事务我也可以使用批处理吗?
    • 是的,您可以单独使用批次或事务,也可以同时使用两者。在您的情况下,您正在执行一次插入和一次更新,因此批处理没有用,一个简单的语句就可以了。
    • 我已经更新了上面的代码,我正在做多次插入并且只有一次更新。也在插入之间,我使用 SELECT 语句从另一个表中获取列的值。上面的代码是否正确?
    • 是的,这似乎是正确的,除了(缺少)异常处理代码。为清楚起见,您应该将 dmlPreparedStatement 重命名为 updateStatement,将 dmlPreparedStatement1 重命名为 updateStatement。此外,您的 select 语句应该使用参数而不是字符串连接。
    • 是的,感谢您的宝贵指导...如果我遇到一些问题,请稍后再联系您。(?) :)
    【解决方案2】:

    PreparedStatement 对象用于多次执行同一 SQL 语句而不是多个 SQL 多次声明。 对应Docs

    SQL 语句被预编译并存储在 PreparedStatement 对象中,因此您可以通过更改输入参数多次执行相同的预编译 SQL 语句,从而提高性能。

    这里不是在改变输入参数,而是在改变 PreparedStatement 对象 通过声明dmlPreparedStatement = dbConnection.prepareStatement(Updatequery);
    然后你在 newley 创建的 Object 上调用 executeBatch() 方法。
    这意味着您将执行最后一个预编译查询并输入前一个查询。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-12
      • 1970-01-01
      • 2014-09-24
      • 1970-01-01
      相关资源
      最近更新 更多