下面是关于“spring的@Transactional注解用法解读”的完整攻略。
什么是@Transactional注解?
@Transactional
是Spring框架中用于实现事务管理的注解。在一个被该注解标注的方法或类上使用该注解,可以使得这个方法或类变为一个事务处理的方法或类,在这个方法或类的执行过程中,会同步进行数据源的事务管理。
@Transactional注解的属性
在使用@Transactional
注解时,可以指定以下属性来控制事务的管理。
propagation
:事务的传播行为,默认值为REQUIRED。包括以下传播行为:- REQUIRED:表示当前方法必须在事务内执行,如果当前上下文中已经有了事务,当前方法就在这个事务内执行,否则就开启一个新的事务。
- REQUIRES_NEW:表示当前方法必须在新的事务内执行,如果当前上下文中已经有了事务,就将该事务挂起,当前方法在新的事务内执行。
- SUPPORTS:表示当前方法支持事务,但可以继承上下文中的事务(如果有)。
- NOT_SUPPORTED:表示当前方法不支持事务,如果存在事务就将其挂起。
- MANDATORY:表示当前方法必须在事务内执行,如果当前上下文中没有事务,就抛出异常。
- NEVER:表示当前方法不能在事务内执行,如果当前上下文中有事务就抛出异常。
-
NESTED:表示当前方法必须在另一个事务内执行,当前方法创建一个新的保存点,并只对这个保存点回滚。
-
isolation
:事务的隔离级别,默认值为DEFAULT,包括以下隔离级别: - DEFAULT:表示使用底层数据源的默认隔离级别。
- READ_COMMITTED:表示事务中操作的数据,只要已经提交,就可以被另一个事务读取,可避免脏读现象。
- READ_UNCOMMITTED:表示无法解决脏读、不可重复读、幻读的问题,不应该在生产环境中使用。
- REPEATABLE_READ:表示事务中操作的数据,只有在当前事务之前已经被锁定,才能被当前事务访问,可避免脏读和不可重复读现象。
-
SERIALIZABLE:表示所有事务必须依次进行,且不能并发执行。
-
timeout
:事务的超时时间,默认值为-1,单位为秒。 -
readOnly
:表明事务是否为只读事务,默认值为false。 -
rollbackFor
:异常类数组,当出现异常时,事务就会回滚。 -
noRollbackFor
:异常类数组,当出现这些异常时,事务不会回滚。
@Transactional在方法上的使用方法
在方法上使用@Transactional
注解时,需要在方法声明上加上该注解。例如:
@Transactional
public void saveUser(User user) {
userDao.save(user);
}
上面的代码中,saveUser
方法在执行时,如果之前还没有开启事务,就会自动开启一个事务;如果当前的方法已经在一个开启的事务内,保存操作将会在该事务内完成;如果该方法执行成功,事务就会被提交,如果其中有一个或多个操作失败,则整个事务会被回滚,所有变更将会被撤回。
@Transactional在类上的使用方法
在类上使用@Transactional
注解时,该注解会应用到所标注的类中的所有方法中。例如:
@Transactional
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void saveUser(User user) {
userDao.save(user);
}
@Override
public void updateUser(User user) {
userDao.update(user);
}
}
上面的代码中,@Transactional
注解标注在了类上,是该类中的所有方法都会受到其影响,如果该类中的任意一个方法当中出现了异常,那么在这个事务的生命周期内,所有未提交的更改都将被回滚。
示例1:事务的嵌套
@Transactional
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveUser(User user) {
userDao.save(user);
}
@Override
public void updateUser(User user) {
userDao.update(user);
// 保存其它业务数据
try {
saveOtherData();
} catch(Exception e) {
throw new RuntimeException("保存其它业务数据失败", e);
}
}
// 保存其它业务数据
private void saveOtherData() {
// do something
}
}
上面的代码中,saveUser
方法的事务传播行为为REQUIRES_NEW,表示该方法已经开启了一个新的事务;在updateUser
方法中调用了saveOtherData
方法,该方法会在当前事务中执行,如果保存数据失败了,就会抛出异常。此时,该异常会被抛到updateUser
方法中,因为该方法在一个已经开启的事务中执行,整个事务就会被回滚,而saveUser
方法开启的事务并不受updateUser
方法的回滚影响,依然会在数据源中保存成功。
示例2:基于异常回滚
@Transactional
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
@Transactional(rollbackFor = RuntimeException.class)
public void saveUser(User user) {
userDao.save(user);
if (StringUtils.isBlank(user.getNickname())) {
throw new RuntimeException("昵称不能为空");
}
}
@Override
public void updateUser(User user) {
userDao.update(user);
}
}
上面的代码中,saveUser
方法的事务标注了rollbackFor
属性,表示只有当该方法抛出RuntimeException时,才会回滚整个方法的所有更改。如果在该方法中执行了若干操作,但其中只有一项出现了问题,其它操作都执行成功了,即使抛出了异常,也只会回滚该方法中失败的操作,而其它成功的操作并不会被回滚。这样就可以避免因为某些无关紧要的操作导致整个事务全部回滚,提高了数据操作的准确性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:spring的@Transactional注解用法解读 - Python技术站