混合 JdbcTemplate 和原始 JDBC

Mixing JdbcTemplate and raw JDBC

我遇到了一些我无法轻易解释的奇怪行为。以下代码运行良好:

    try (Connection connection = dataSource.getConnection();
         Statement statement = connection.createStatement()) {
        statement.executeUpdate("DELETE FROM product");

    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }

    try (Connection connection = dataSource.getConnection();
         Statement statement = connection.createStatement()) {
         statement.executeUpdate("INSERT INTO product ...");

    } catch (SQLException ex) {
        throw new RuntimeException(ex);
    }

但是这段代码会导致死锁:

    jdbcTemplate.update("DELETE FROM product");

    try (Connection connection = dataSource.getConnection();
         Statement statement = connection.createStatement()) {
         statement.executeUpdate("INSERT INTO product ...");

    } catch (SQLException ex) {
        throw new RuntimeException(ex);
    }

例外是

java.sql.SQLException: 超过锁等待超时时间;尝试重新启动交易

jdbcTemplate 和 dataSource 都是由 Spring boot 和 autowired 创建的

@Autowired
private DataSource dataSource;

@Autowired
private JdbcTemplate jdbcTemplate;

语句构成服务中方法的一部分(使用@Transactional 注释)

谁能解释为什么会这样?

如果你想使用自己的 JDBC 代码来很好地处理由 Spring 的事务管理管理的连接,你应该使用 DataSourceUtils 来获取连接——参见 http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/datasource/DataSourceUtils.html#getConnection-javax.sql.DataSource-

在您的示例中,根据事务配置,使用 JdbcTemplate 的第一条语句可能尚未提交,因此它会阻止来自不同连接的下一个 JDBC 语句。使用 DataSourceUtils,两个语句将使用相同的连接。