JAVA数据库操作回滚小结
一:总结的原因
在最近的工作中,遇到了一个一对多关系多表数据传输,传送成功状态绑定在主数据表上,因为代码不健壮问题造成了主表传送状态更新失败,而子表数据就被重复插入。又由于数据传输频率很高,我们的测试环境就像被官方病毒攻击,疯狂插入了几十个G的数据……
二:解决步骤
1.提高代码健壮性,先进行主表状态能否成功更新判断,再插入子表数据,最后再更新主表状态。
2.进一步提高容错率:将这些存在关系的表的更新集成到一个事物,全部更新都正常执行后,再提交事务。
三:技术实现
public void doManipulateData(){ Connection connection = getConnection();//获取当前环境的连接 try { connection.setAutoCommit(false);//设置不能自动提交 //1.执行普通的增删改查语句 doADUS(connection); //2.执行存储过程 doStoredPro(connection); connection.commit(); //手动提交 connection.setAutoCommit(true);//设置可以自动提交 } catch (SQLException e) { try { connection.rollback(); //回滚此次链接的所有操作 connection.setAutoCommit(true); //设置可以自动提交 } catch (SQLException e1) { e1.printStackTrace(); } } finally { connection.close();//关闭连接 } } /* * 执行普通的增删改查语句 */ public void doADUS(Connection connection) throws Exception{ String sql = "..."; PreparedStatement ps = null; try { ps = connection.prepareStatement(sql); ps.setString(1, appId); //ps.setBinaryStream(2, arg1, arg2) ps.executeUpdate(); } catch (SQLException e) { throw e; } finally { ps.close(); } } /* * 执行存储过程 */ public void doStoredPro(Connection connection) throws Exception{ CallableStatement cs = null; try { cs = connection.prepareCall("{call 过程名称(?,?)}"); cs.setString(1, ""); cs.registerOutParameter(2, Types.INTEGER);//存储过程执行返回数据 cs.execute(); if (cs.getInt(2) != 0) { throw new Exception("存储过程执行失败!"); } } catch (Exception e) { throw e; } finally { ps.close(); } }
四:注意事项
1.java.sql.PreparedStatement.setBinaryStream(int parameterIndex, InputStream x, long length) 方法,jdbc并没有提供相应的接口,运行时会报错。需要使用 java.sql.PreparedStatement.setBinaryStream(int parameterIndex, InputStream x, int length)
2.PreparedStatement 建立的sql对象只编译一次,可使用占位符安全的插入。Statement每次执行sql时都会重新编译一次sql,不能使用占位符