前言
JdbcTemplate是spring-jdbc提供的数据库核心操作类,那对JdbcTemplate进行事务控制呢?
我的环境:spring-boot-2.1.3,druid-1.1.3。
原生Jdbc的事务控制
即,批处理+自动提交的控制方式,
public static void demo(String[] args) throws SQLException, ClassNotFoundException { String url = "jdbc:mysql://10.1.4.16:3306/szhtest"; String username = "ababab"; String password = "123456"; String sql1 = "insert xx"; String sql2 = "insert xx"; Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection(url, username, password); Statement statement = conn.createStatement(); // 获取到原本的自动提交状态 boolean ac = conn.getAutoCommit(); // 批处理多条sql操作 statement.addBatch(sql1); statement.addBatch(sql2); // 关闭自动提交 conn.setAutoCommit(false); try { // 提交批处理 statement.executeBatch(); // 若批处理无异常,则准备手动commit conn.commit(); } catch (Exception e) { e.printStackTrace(); // 批处理抛异常,则rollback try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } finally { // 恢复到原本的自动提交状态 conn.setAutoCommit(ac); if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
Spring的声明式事务控制
Bean的类或方法上加@Transactional,事务控制粒度较大,只能控制在方法级别,不能控制到代码粒度级别。
尝试JdbcTemplate的事务控制
采取跟原生jdbc事务控制一样的方法试试,在批处理前关闭自动提交,若批处理失败则回滚的思路。
@RequestMapping("/druidData1") public String druidData1() throws SQLException { String sql1 = "INSERT INTO user_tmp(`id`, `username`) VALUES(22, 222)"; // id=1的主键冲突<p>本文来源gao!%daima.com搞$代*!码9网(</p>插入失败 String sql2 = "INSERT INTO user_tmp(`id`, `username`) VALUES(1, 111)"; Connection conn = jdbcTemplate.getDataSource().getConnection(); LOG.info("1:{}", conn); boolean ac = conn.getAutoCommit(); conn.setAutoCommit(false); try { int[] rs2 = jdbcTemplate.batchUpdate(new String[]{sql1, sql2}); conn.commit(); } catch (Throwable e) { LOG.error("Error occured, cause by: {}", e.getMessage()); conn.rollback(); } finally { conn.setAutoCommit(ac); if (conn != null) { try { conn.close(); } catch (SQLException e) { LOG.error("Error occurred while closing connectin, cause by: {}", e.getMessage()); } } } return "test"; }
期望结果:id=1的因为主键冲突,所以id=22的也要回滚。