Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果PreparedStatement遇到暂时异常,我可以重用它吗?_Java_Mysql_Jdbc_Innodb - Fatal编程技术网

Java 如果PreparedStatement遇到暂时异常,我可以重用它吗?

Java 如果PreparedStatement遇到暂时异常,我可以重用它吗?,java,mysql,jdbc,innodb,Java,Mysql,Jdbc,Innodb,我有一段代码更新数据库中的记录。简化示例: ... statement = connection.prepareStatement( "INSERT INTO thistable (name) VALUES (?)", PreparedStatement.RETURN_GENERATED_KEYS ); statement.setString( 1, "Fred" ); statement.addBatch( ); statement.setString( 2, "Joe" );

我有一段代码更新数据库中的记录。简化示例:

...
statement = connection.prepareStatement(
    "INSERT INTO thistable (name) VALUES (?)",
    PreparedStatement.RETURN_GENERATED_KEYS
);
statement.setString( 1, "Fred" );
statement.addBatch( );
statement.setString( 2, "Joe" );
statement.addBatch( );
statement.executeBatch( );
...
这是一些处理大量记录的代码的一部分,为了提高速度,代码运行了大量线程。这很好,但是随着实时环境中负载的增加,我注意到一些
SQLTransientException
s被抛出。似乎除了重试事务之外,我什么都做不了

我的问题是:即使语句失败,批处理是否可以被清除?我可以简单地重试
executeBatch
行,还是需要重新创建整个批?对于非批处理语句也是这样吗


简而言之,更一般地说,这是处理瞬时异常的好方法吗

statement.setString( 1, "Fred" );
statement.addBatch( );
statement.setString( 2, "Joe" );
statement.addBatch( );
for( int attempt = 0; ; attempt ++ ) {
    try {
        statement.executeBatch( );
        break;
    } catch( SQLTransientException ex ) {
        if( attempt >= 3 ) {
            throw ex;
        }
        try {
            Thread.sleep( attempt * attempt * 100 );
        } catch( InterruptedException ex2 ) {
            throw ex;
        }
    }
}
因为除了下面的内容之外,没有提供关于SQLTransientException发生时的行为的更多信息

 when the driver has determined that the timeout value that was specified by the 
 setQueryTimeout method has been exceeded and has at least attempted
 to cancel the currently running Statement
验证了Mysql JDBC4实现

在我的观察中,我可以看到如果超时,可能会发生一种
SQLTimeoutException
(即
sqltransienteexception

当超时时,它不仅清除最后的语句,还清除整个批处理(至少在MYSQL实现中)

这一部分很清楚

并符合JDBC规范

The statement’s batch is reset to empty once executeBatch returns
无论executeBatch抛出异常/成功与否,它都将清除该批

特别是Mysql
Prepared语句
在executeBatch()方法中清除finaly块处的批处理

因此,您的逻辑将不起作用,因为您不会再次将语句添加到批处理中


因此,将语句添加回批处理并重新执行。很有可能你会再次超时。所以,首先找出时间。如果可能,在执行日志中写一些关于原因/状态的信息。

异常消息是什么?不确定是否由于mysql连接问题而失败。此外,我认为处理一个很长的请求并不好。您可以通过逐件运行来多次运行它,以实现您的目标。

我将此问题标记为MySQL,因为这是我们当前使用的问题,但我希望了解标准行为,而不是特定于实现的行为,因为我们很快就要迁移到Postgres。理论上,只有当错误允许在没有“应用程序级功能的任何干预”的情况下重试操作时,才应该抛出
SQLTransientException
。您对此异常有任何SQL状态(getSQLState())?@Mani,恐怕我不知道它的存在,所以我没有把它记录下来。@user2574853的回答评论:虽然我发布的示例没有说明它,但每个批次添加的大约10条记录实际上是一个批次;它们都与同一个项目相关,如果其中任何一个项目失败,那么添加其他项目就没有意义了。手动清除(以防万一)并重新填充即可。遗憾的是,我希望这可以隐藏在一个方法中。只是为了补充(对于未来的访问者)关于非批处理语句的相关问题,根据此文档,这些值不需要重新填充:在对问题的评论中回答了这一点。作为将来的参考,您不应将评论/问题作为答案发布。
The statement’s batch is reset to empty once executeBatch returns
finally {
        this.statementExecuting.set(false);
        clearBatch();
        }