Spring 编程的方式实现事务管理,这样太过麻烦,需要在每个方法上面加上相应的事务处理操作,声明式事务处理能够很好的解决这个问题,比如通过tx命名空间,这样只需要配置就可以检测到相关的方法,或者是通过@transcational注解来实现,这样会减少很多的代码量,但是实现的时候有这样的几个点需要注意
首先我们来看tx命名空间来实现:
<tx:advice id="transcation" transaction-manager="transcationManager"><tx:attributes><tx:method name="*" propagation="REQUIRED" isolation="DEFAULT"></tx:method></tx:attributes></tx:advice><aop:config><aop:pointcut expression="execution(* com.aa.dao.api.IStudentDao.tranfMoeny(..))" id="transcationCut" /><aop:advisor advice-ref="transcation" pointcut-ref="transcationCut"/></aop:config>
配置如上图:
需要配置aop:config ,因为Spring 事务管理是基于aop来进行实现的,在aop:config 中我们配置了切点 pointcut 和一个advisor 什么是advisor 呢,我们来看一下:
然后使用tx 来配置事务通知,
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!-- 所有以 'get' 开头的方法使用只读事务 --><tx:method name="get*" read-only="true"/><!-- 其他方法使用默认的事务属性 --><tx:method name="*"/></tx:attributes>
</tx:advice>
id
属性为事务通知指定一个唯一的标识符。transaction-manager
属性指定使用的事务管理器。<tx:attributes>
标签内可以定义不同方法名匹配规则下的事务属性。name
属性用于指定方法名的匹配规则,支持通配符*
。read-only
属性用于指定事务是否为只读事务。
然后我们去执行方法的时候,如果出现了异常就会执行相应的回滚的操作,对于目标方法,我们可以这样设置:
@Overridepublic void tranfMoeny(String money, String fromname, String targetName) {String sql_sub = "update t_account set money=money-" + money + " where username=\'" + fromname + "\'";jdbcTemplate.execute(sql_sub);Integer.parseInt("jjf");//模拟出现异常String sql_add = "update t_account set money=money+" + money + " where username=\'" + targetName + "\'";jdbcTemplate.execute(sql_add);}
或者:
@Overridepublic void tranfMoeny(String money, String fromname, String targetName) {try {String sql_sub = "update t_account set money=money-" + money + " where username=\'" + fromname + "\'";jdbcTemplate.execute(sql_sub);Integer.parseInt("jjf");String sql_add = "update t_account set money=money+" + money + " where username=\'" + targetName + "\'";jdbcTemplate.execute(sql_add);} catch (Exception e) {e.printStackTrace();throw new RuntimeException("数据插入异常");}}
非常重要的一点是,目标方法需要有异常抛出,我们可以手动抛出,或者默认抛出异常的方式,这样我们的事务管理器就可以检测到,并且执行回滚操作。
希望对你有所帮助!