在使用Transaction事务的方法中,catch到异常并手动进行事务回滚。

今天在做使用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();
            }

这样,便能让事务回滚了又捕获到异常了。

原文地址:https://www.cnblogs.com/libera11/p/8054072.html