今天刚刚接触了@Transactional注释,把自己所学到的内容先整理一下,首先,这里没有详细的理论知识,看了反正是我记不住。
例子
这是一个购物网站的关于收货地址的一个模块
@Transactional
@Override
public void setDefault(Integer uid, Integer aid){
// 根据aid查询数据
Address result = findByAid(aid);
// 判断数据是否为null
if (result == null) {
// 是:AddressNotFoundException
throw new AddressNotFoundException(
"设置默认收货地址失败!尝试访问的数据不存在!");
}
// 判断参数uid与查询结果中的uid是否不一致
if (!result.getUid().equals(uid)) {
// 是:AccessDeniedException
throw new AccessDeniedException(
"设置默认收货地址失败!数据归属错误!");
}
// 全部设置为非默认
updateNonDefault(uid);
// 把指定的设置为默认
updateDefault(aid);
}
解析
updateNonDefault(uid) 和 updateDefault(aid) 这两个是本类中的方法,为什么这么写,高聚能,低耦合 嘛。这两个方法都涉及到了与数据库的update操作,如果updateNonDefault方法成功,updateDefault方法失败,这时候 @Transactional 就会起到作用 事务回滚,回滚到 updateNonDefault 方法执行前的状态,换句话说:你怎么改的就怎么给我改回来。
【附】基于SpringJDBC的事务
关于事务:使用事务可以保证同一个业务中的多条SQL语句产生的数据修改(增删改)要么全部成功,要么全部失败!
所以,可以认为:如果某个业务中涉及超过1次的增、删、改操作(例如需要执行2次Update,或1次Update加上1次Delete),则应该使用事务!
在使用了SpringJDBC后(无视使用哪种数据库,或使用哪种持久层框架),当需要使用事务来保障数据操作时,只需要在相关的业务方法之前添加@Transactional注解即可!
该注解也可以添加在业务类之前,表示该业务类中所有业务方法都是有事务的保障的!
在SpringJDBC中,事务的处理过程大致是:
开启事务:begin
try {
执行若干条SQL
提交:commit
} catch (RuntimeException e) {
回滚:rollback
}
也就是说,框架在处理时,一旦执行的SQL语句抛出了RuntimeException,就会导致事务回滚。
小结
所以,关于SpringJDBC中事务的应用小结:
- 所有的增、删、改操作都应该获取其受影响的行数,如果不是预期值,就必须抛出RuntimeException或其子孙类异常,则后续该操作被应用于事务中时,才可以实现回滚效果!
- 如果某个业务中涉及超过1次的增、删、改操作(例如需要执行2次Update,或1次Update加上1次Delete),则应该在业务方法之前添加@Transactional!
如果使用的不是SpringBoot,而是传统的SSM框架,则需要在Spring的>配置文件中配置<tx:annotation-driven transaction-manager=“xxx” />和id=“xxx” class=“DataSourceTransactionManager”>name=“dataSource” ref=“xxxxx” />。