Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.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 已准备好的报表赢得';即使显式设置,也不会超时_Java_Mysql_Jdbc_Prepared Statement_Hikaricp - Fatal编程技术网

Java 已准备好的报表赢得';即使显式设置,也不会超时

Java 已准备好的报表赢得';即使显式设置,也不会超时,java,mysql,jdbc,prepared-statement,hikaricp,Java,Mysql,Jdbc,Prepared Statement,Hikaricp,我试图模拟这样一种场景:我的服务与数据库失去连接,无法通过使用iptables阻止连接来执行插入操作,但我无法使executeQuery()方法超时 我所做的是为PreparedStatement设置超时,如下面的语句。setQueryTimeout(5)。这是代码 HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://db-url/db"); config.setUsername("user");

我试图模拟这样一种场景:我的服务与数据库失去连接,无法通过使用iptables阻止连接来执行
插入操作,但我无法使
executeQuery()
方法超时

我所做的是为PreparedStatement设置超时,如下面的
语句。setQueryTimeout(5)
。这是代码

HikariConfig config = new HikariConfig();

config.setJdbcUrl("jdbc:mysql://db-url/db");
config.setUsername("user");
config.setPassword("passwd");

config.setMaximumPoolSize(10);
config.setAutoCommit(false);
config.setConnectionTimeout(5000);
config.setDriverClassName("com.mysql.jdbc.Driver");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.addDataSourceProperty("autoReconnect", "true");

final HikariDataSource pool = new HikariDataSource(config);

final String query = "INSERT INTO xtable VALUES (?, ?, ?, ?, ?)";

try ( Connection connection = pool.getConnection() )
{
    try ( PreparedStatement statement = connection.prepareStatement(query) )
    {
        // this is what I expect to work
        statement.setQueryTimeout(5);

        for ( Info info : infos )
        {
            statement.setString(1, info.getValue1());
            statement.setString(2, info.getValue2());
            statement.setString(3, info.getValue3());
            statement.setString(4, info.getValue4());
            statement.setString(5, info.getValue5());

            try
            {
                System.out.println("Waiting");
                Thread.sleep(5000);
                // I use this sleep to ban the database url with iptables
                // to simulate a disconnection
                System.out.println("Waited");
            }
            catch ( InterruptedException e )
            {
                e.printStackTrace();
            }

            System.out.println("Before executeQuery");
            statement.executeQuery();
            // I assumed that this would timeout after 5 seconds
            // But it never reaches the next System.out.print
            System.out.println("After executeQuery");
        }
    }

    System.out.println("Before commit");
    connection.commit();
    System.out.println("After commit");
}
catch ( SQLException e )
{
    log.error("Couldn't execute query", e);
}
产出将是:

Waiting
Waited
Before executeQuery
然后它永远挂着。。。如何使其抛出异常?

您始终可以:

try{
     preparedstatement = connection.prepareStatement(query);
     preparedstatement.setQueryTimeout(seconds);
}
而不是你所做的。也许那样会更好。 同样的道理也适用于:

Connection connection = pool.getConnection() 

调用
Connection.setNetworkTimeout()
,然后再试一次


您正遭受未确认的TCP通信,如果未设置网络超时,可能会挂起连接。

这会有什么区别?@fcasanova调试时,更容易判断哪一行在哪个值之后抛出了哪个异常或错误。这不是一个答案,而是一个发现它为什么不起作用的建议。它似乎很好,谢谢!有两件事困扰着我:一是在connection.close()中,它会关闭,另一个是uncatched异常,因为它在网络超时后无法关闭。另外:我是否每次都必须设置此超时?如果我有一个Hikari池,每次我需要连接时都设置它似乎是胡说八道,对吗?我的意思是,主要是因为我会继续创建执行器。另一个选择是在驱动程序级别设置网络超时-全局设置。在这种情况下,我建议将其设置为最长查询时间的3倍。请注意最后一点。您不需要继续创建执行器。正如上面的例子,您可以(应该)创建一个静态执行器,该执行器(在MySQL的情况下)应该立即执行Runnable,而不是排队或传递到另一个线程。好的建议,我会尝试。我无法在jdbc驱动程序级别设置网络超时。谢谢
private final static Executor immediateExecutor = Runnable::run;

try ( Connection connection = pool.getConnection() ) {
   int timeout = connection.getNetworkTimeout();
   connection.setNetworkTimeout(immediateExecutor, TimeUnit.SECONDS.toMillis(5));
   ...
   try (PreparedStatement...) {
      ...
   }
   finally {
      connection.setNetworkTimeout(timeout);
   }
}
finally {
   ...
}