今天在做使用Quartz进行定时更新数据操作时,发现在加了事务的方法在try{}catch{}捕获异常的时候,事务无法进行回滚。
这个是添加事务的接口:
/** * 更新实时数据 */ @Transactional public Map<String,Object> batchAddHik();
实现类捕获异常代码块:
/** * 定时批量更新数据 */ @Override public Map<String,Object> batchAddHik() { //.. Map<String,Object> map = new HashMap<String, Object>(); final List<Object[]> insertParams = new ArrayList<Object[]>(); for (ClInout clInout : clInouts) { String plateNo = clInout.getPlateNo(); String crossTime = clInout.getCrossTime(); Integer releaseMode = clInout.getReleaseMode(); Integer vehicleSize = clInout.getVehicleSize(); Integer carOut = clInout.getCarOut(); String platePicUrl = clInout.getPlatePicUrl() == null ? "" : clInout.getPlatePicUrl(); String vehiclePicUrl = clInout.getVehiclePicUrl() == null ? "" : clInout.getVehiclePicUrl(); String facePicUrl = clInout.getFacePicUrl() == null ? "" : clInout.getFacePicUrl(); String hikRecordUuid = clInout.getHikRecordUuid(); insertParams.add(new Object[] {plateNo,crossTime,releaseMode,vehicleSize,carOut,platePicUrl,vehiclePicUrl,facePicUrl,hikRecordUuid}); } String sql = "INSERT INTO cl_inout (plate_no, cross_time, release_mode, vehicle_size, car_out, plate_pic_url, vehicle_pic_url, face_pic_url, hik_record_uuid)" + "VALUES (?,?,?,?,?,?,?,?,?)"; if (clInouts.size() > 0) { try { num = this.getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { Object[] args = insertParams.get(i); ps.setString(1, (String) args[0]); ps.setString(2, (String) args[1]); ps.setInt(3, (Integer) args[2]); ps.setInt(4, (Integer) args[3]); ps.setInt(5, (Integer) args[4]); ps.setString(6, (String) args[5]); ps.setString(7, (String) args[6]); ps.setString(8, (String) args[7]); ps.setString(9, (String) args[8]); } @Override public int getBatchSize() { return insertParams.size(); } }); } catch (Exception e) { e.printStackTrace(); String message = e.getMessage(); map.put("exception", message); map.put("number", 0); } } //.. }
此时,在batchUpdate过程若catch到异常,事务将无法回滚,程序依然会将部分插入到数据库中。
解决办法:
spring在捕获RuntimeException异常后,才会进行事务回滚。
故,在catch代码块中,添加:
} catch (Exception e) { e.printStackTrace(); String message = e.getMessage(); map.put("exception", message); map.put("number", 0); // 手动设置当前事务回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); // 或者手动抛出runTimeException // throw new RuntimeException(); }
这样,便能让事务回滚了又捕获到异常了。