You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot调用Azure SQL Server长时存储过程的优化方案咨询

问题:Azure SQL Server长耗时存储过程调用的SocketTimeout问题及优化需求

场景与问题详情

我需要在Azure SQL Server上运行一个耗时约20分钟的存储过程,最初采用Spring Data JPA的方式调用,代码如下:

public interface MyRepository extends JpaRepository<MyEntity, Integer> {
    @Procedure(procedureName = "my_procedure")
    void my_procedure();
}

private void importProcedure(){
    repository.my_procedure();
}

@Transactional(propagation = Propagation.REQUIRES_NEW, timeout = 6)
public void import_procedure_conferimenti() {
    log.info("Start");
    CompletableFuture<Void> future = CompletableFuture.runAsync(this::importprocedure);
    future.thenAccept(result -> {
        log.info("Finish");
    }).exceptionally(throwable -> {
        log.error("Error", throwable);
        return null; // Return a default value in case of an error
    });
}

对应的Spring数据源配置:

datasource:
  driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
  url: jdbc:sqlserver://db:port;database=db-name;user=user;password=pwd;...;socketTimeout=60000
  hikari:
    minimum-idle: 10
    maximum-pool-size: 50

但这种方式因URL中的socketTimeout=60000参数触发了SocketTimeout错误,原因是等待响应的套接字超时导致。

当前临时解决方案

我通过直接操作JDBC连接的方式解决了该问题,代码如下:

public Object executeProcedure(String procedureCall, int networkTimeoutMillis, int queryTimeoutSeconds) {
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultSet = null;
    Object result = null;
    try {
        connection = DataSourceUtils.getConnection(dataSource);
        connection.setNetworkTimeout(null, networkTimeoutMillis);

        preparedStatement = connection.prepareStatement(procedureCall);
        preparedStatement.setQueryTimeout(queryTimeoutSeconds);
        boolean hasResultSet = preparedStatement.execute();
        if (hasResultSet) {
            resultSet = preparedStatement.getResultSet();
            if (resultSet.next()) {
                result = resultSet.getObject(1);  // Return the result as an Object
            }
        }
    } catch (SQLException e) {
        log.error("Error during procedure execution: " + e.getMessage(), e);
    } finally {
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                log.error("Error: " + e.getMessage(), e);
            }
        }
        if (connection != null) {
            DataSourceUtils.releaseConnection(connection, dataSource);
        }
    }
    return result;
}

该方法能正常运行,但我不确定这是否为最优方案,因为需要为每个过程指定自定义超时。

期望实现的目标

我希望能实现以下效果:

  • 调用存储过程
  • 关闭连接以避免SocketTimeout
  • 在处理过程中接收响应
  • 完成时获取结果(考虑采用轮询方式?)

相关环境:Spring Boot 2.3,Java 1.8。

内容的提问来源于stack exchange,提问作者faienz93

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 03:36:02