在此,首先我们要明确RuntimeException与Exception之间的关系与他们分别的含义:

①在Java中异常的基类为Throwable,他有两个子类Exception与Errors,同时RuntimeException就是Exception的子类;

②RuntimeException,即运行时异常,为非受检(UNCHECKED)异常;

③Exception的其他子类异常,为非运行时异常,为受检异常(CHECKED)异常;

1,Spring事务回滚机制是这样的:当所拦截的方法有指定异常抛出,事务才会自动进行回滚!

我们需要注意的地方有四点: 如果你在开发当中引入Spring进行事务管理,但是事务没能正常的自动回滚,可以对照下面四点,缺一不可!

①被拦截方法-—— 注解式:方法或者方法所在类被@Transactional注解;

拦截配置式:应该包含对该方法,名称格式的定义;

且方法需要在expression定义的范围内;

②异常—— 该方法的执行过程必须出现异常,这样事务管理器才能被触发,并对此做出处理;

③指定异常——  默认配置下,事务只会对Error与RuntimeException及其子类这些UNChecked异常,做出回滚。

一般的Exception这些Checked异常不会发生回滚(如果一般Exception想回滚要做出配置);

如果你不知道哪些是RuntimeException或者你觉得在默认配置下发生一般的Exception,事务也能如愿回滚,请访

举例:实现一般异常的回滚:

注解式:

@Transactional(rollbackFor=Exception.class)
@RequestMapping("consump")
public void insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{
拦截配置式:
@RequestMapping("consump")
public void insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{
④异常抛出—— 即方法中出现的指定异常,只有在被事务管理器捕捉到以后,事务才会据此进行事务回滚;
1,不捕捉,会回滚:
public void insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{
int a=consumpDao.insert(s);
int b=customerDao.update(customer);
}
2,如果异常被try{}捕捉到,那么事务管理器就无法再捕捉异常,所以就无法做出反应,事务不回滚;
public void insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{
try{
int a=consumpDao.insert(s);
int b=customerDao.update(customer);
}catch(RuntimeException){
}
}
3,如果异常被try{}捕捉了,我们还可以在Catch(){}中throw   new  RuntimeException(),手动抛出运行时异常供事务管理器捕捉;
public void insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{
try{
int a=consumpDao.insert(s);
int b=customerDao.update(customer);
}catch(){
throw new RuntimeException();
}
}
2,在实际开发中,有时并没有异常发生,但是由于事务结果未满足具体业务需求,所以我们不得不手动回滚事务!
有如下两种方法:
①手动抛出异常(如果你没有配置一般异常事务回滚,请抛出运行时异常)
int a=consumpDao.insert(s);
int b=customerDao.insert(customer);
int d=0;//制造未被满足的业务需求
if(a*b*d==1){
json.put("result",0);
json.put("msg", "购买成功");
json.put("data", "");
}else{
json.put("result",-1);
json.put("msg", "购买失败");
json.put("data", "");
throw new RuntimeException();
}
②编程式实现手动回滚
int a=consumpDao.insert(s);
int b=customerDao.insert(customer);
int d=0;//制造未被满足的业务需求
if(a*b*d==1){
json.put("result",0);
json.put("msg", "购买成功");
json.put("data", "");
}else{
json.put("result",-1);
json.put("msg", "购买失败");
json.put("data", "");
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}

注意:尽管可以采用编程式方法回滚事务,但“回滚”只是事务的生命周期之一,所以要么编程实现事务的全部必要周期,要么仍要配置事务切点,即,将事务管理的其他周期交由Spring的标识!