一站式异常处理(spring AOP事务回滚问题)


异常的类别

ava中的异常的超类是java.lang.Throwable(后文省略为Throwable),它有两个比较重要的子类,java.lang.Exception(后文省略为Exception)和java.lang.Error(后文省略为Error),其中Error由JVM虚拟机进行管理,如我们所熟知的OutOfMemoryError异常等,所以我们本文不关注Error异常,那么我们细说一下Exception异常。

Exception异常有个比较重要的子类,叫做RuntimeException。我们将RuntimeException或其他继承自RuntimeException的子类称为非受检异常(unchecked Exception),其他继承自Exception异常的子类称为受检异常(checked Exception)。本文重点来关注一下受检异常和非受检异常这两种异常。


如何选择异常

从笔者的开发经验来看,如果在一个应用中,需要开发一个方法(如某个功能service方法),这个方法如果中间可能出现异常,那么你需要考虑这个异常出现之后是否调用者可以处理,并且你是否希望调用者进行处理,如果调用者可以处理,并且你也希望调用者进行处理,那么就要抛出受检异常,提醒调用者在使用你的方法时,考虑到如果抛出异常时如果进行处理,相似的,如果在写某个方法时,你认为这是个偶然异常,理论上说,你觉得运行时可能会碰到什么问题,而这些问题也许不是必然发生的,也不需要调用者显示的通过异常来判断业务流程操作的,那么这时就可以使用一个RuntimeException这样的非受检异常

 

应该抛出怎样的异常

究竟是受检异常还是非受检异常呢(RuntimeException)

受检异常如:需要从某文件中读取某个数据,这个读取操作可能是由于文件被删除等其他问题导致无法获取从而出现读取错误。用try catche 等捕捉。

非受检异常比如java.lang.NullPointerExceptionjava.lang.IllegalArgumentException等

当我们在写某个方法的时候,可能会偶然遇到某个错误,我们认为这个问题时运行时可能为发生的,并且理论上讲,没有这个问题的话,程序将会正常执行的时候,它不强制要求调用者一定要捕获这个异常,此时抛出RuntimeException异常,举个例子,当传来一个路径的时候,需要返回一个路径对应的File对象:

  if(null == path || "".equals(path)){

        throw  new NullPointerException("路径不能为空!");(如果有事务就会回滚)

    }

应该选用哪种异常

通过以上的描述和举例,可以总结出一个结论,RuntimeException异常和受检异常之间的区别就是:是否强制要求调用者必须处理此异常,如果强制要求调用者必须进行处理,那么就使用受检异常,否则就选择非受检异常(RuntimeException)。一般来讲,如果没有特殊的要求,我们建议使用RuntimeException异常。


api异常设计

大致有两种抛出的方法:

抛出带状态码RumtimeException异常

抛出指定类型的RuntimeException异常




异常与spring AOP事务回滚:

Spring事务为什么不会自动回滚?Spring事务怎样才会自动回滚?事务自动回滚条件及手动回滚


spring的事物(Transactional  或者xml配置的)与同步锁synchronized   不能同时用:
@Transactional  synchronized  要分开使用,因为加上@Transactional  spring AOP管理事务时,synchronized  并不起作用,可以新建一个不带事务的同步方法,该同步方法在调用investProject(InvestProjBO tp)方法。
例如:@Transactional(propagation = Propagation.REQUIRES_NEW)
public synchronized Map investSure(LendInfo lendInfo,
String userId, String checkCode, String orderNo, String redReceiveId) {
Account account = accountService.get(userId);
Map map = new HashMap();}
其实上并发时是无效的。

可以通过抛出运行异常,将事物回滚:
try {
int rows = this.bidInfoDao.updateBidInfoByParams(params);
if (1 != rows ) {
logger.debug("更新债权不是一条记录,债权编码:"+params.get("bidCode"));
throw new RuntimeException("更新债权不是一条记录");
}
} catch (Exception e) {
logger.error("投资时,更新债权信息报异常:"+e.getMessage());
throw new RuntimeException("313");
}
如果配置了声明式事务,在出现运行时异常时,事务会回滚,但是出现非运行时异常时,事务不回滚。
* 如果配置了编程式事务,则不管出现什么异常,事务都会回滚。
类似亲密理财项目跑的是运行异常,
public int changeUserAccountAmount(Map parms){
           int rows=this.accountDao.changeUserAccountAmount(parms);
           if (rows != 1) {
                 throw new RuntimeException(" 更新账户信息不是一条! ");
           }
           return rows;
      }
http://blog.csdn.net/yipanbo/article/details/46048413
http://shaohan126448.iteye.com/blog/1536879
一般不需要在业务方法中catch异常,如果非要catch,在做完你想做的工作后(比如关闭文件等)一定要抛出runtime exception,否则spring会将你的操作commit,这样就会产生脏数据.所以你的catch代码是画蛇添足。

http://blog.csdn.net/qq_32331073/article/details/76508147


 

 感谢http://mp.weixin.qq.com/s/j8vc1g51geIvGvgEvCvi-w

http://blog.csdn.net/qq_32331073/article/details/76508147

你可能感兴趣的:(java)