混合 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,两个语句将使用相同的连接。
我遇到了一些我无法轻易解释的奇怪行为。以下代码运行良好:
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,两个语句将使用相同的连接。