更多文章:http://zhuqiuhui.space/
场景一 Exception回滚
Case 1:插入操作回滚
@Transactional
public int insertUser(User user) {
int num = iUserDao.insertUser(user);
if (num > 0) {
throw new RuntimeException();
}
return num;
}
Case 2: 插入操作不回滚
@Transactional
public int insertUser(User user) throws Exception{
int num = iUserDao.insertUser(user);
if (num > 0) {
throw new Exception();
}
return num;
}
Case 3: 插入操作回滚
@Transactional(rollbackFor = Exception.class)
public int insertUser(User user) throws Exception{
int num = iUserDao.insertUser(user);
if (num > 0) {
throw new Exception();
}
return num;
}
场景二 propagation属性
Case 1: (1)调用insertUser的方法不在事务中,正常插入。
(2)调用insertUser的方法在事务中,不会插入。
解释: PROPAGATION_SUPPORTS表示:如果当前在事务中,即以事务的形式运行,如果当前不在一个事务中,那么就以非事务的形式运行。只读标志只在事务启动时应用。若调用该方法的方法不在事务中,则就执行成功(因为没有启动任何事务,所以只读标志被忽略)。若在事务中,会回滚插入操作。
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public int insertUser(User user) {
int num = iUserDao.insertUser(user);
return num;
}
Case 2: 抛出异常:java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public int insertUser(User user) throws Exception{
int num = iUserDao.insertUser(user);
return num;
}
Case 3:(1)执行失败(2)执行失败 抛出异常java.lang.RuntimeException
(重要:此处三个函数在同一个类文件中,异常必须抛出,由Spring来捕捉)
@Transactional(propagation= Propagation.REQUIRED)
public void testModifyUser(User user) throws Exception {
insertUser(user); -------(1)
user.setId(13);
updateUser(user); -------(2)
}
@Transactional(propagation= Propagation.REQUIRES_NEW)
public int insertUser(User user) throws Exception{
int num = iUserDao.insertUser(user);
return num;
}
@Transactional(propagation= Propagation.REQUIRES_NEW)
public int updateUser(User user) throws Exception{
//更新语句......
throw new RuntimeException(); //运行时异常 ---------(3)
}
注意:(3)处替换为“throw new FileNotFoundException();”或者“throw new Exception();”(非运行时异常),(1)(2)均执行成功,并抛出相应的异常!
Case 4:(1)执行失败(2)执行失败 抛出异常java.lang.RuntimeException
(重要:此处三个函数在同一个类文件中,异常必须抛出,由Spring来捕捉才能回滚)
@Transactional(propagation= Propagation.REQUIRED)
public void testModifyUser(User user) throws Exception {
insertUser(user); -------(1)
user.setId(13);
updateUser(user); -------(2)
}
public int insertUser(User user) throws Exception{
int num = iUserDao.insertUser(user);
return num;
}
public int updateUser(User user) throws Exception{
//更新语句......
int cnt = iUserDao.updateUser(newvalue, conds);
if(cnt > 0) {
throw new RuntimeException(); ---------(3)
}
}
注意:(3)处替换为“throw new FileNotFoundException();”或者“throw new Exception();”,(1)(2)均执行成功,并抛出相应的异常!
场景三 业务场景
Case 1: (1)(2)都没有成功,并抛出java.lang.RuntimeException异常
(重要:此处四个函数在同一个类文件中,异常必须抛出,由Spring来捕捉才能回滚)
@Transactional
public void testModifyUser(User user) throws Exception {
insertUser(user); -------(1)
B(user); -------(2)
}
// 私有方法
private void B(User user) throws Exception {
user.setId(13);
updateUser(user);
}
public int insertUser(User user) throws Exception{
int num = iUserDao.insertUser(user);
return num;
}
@Transactional
public int updateUser(User user) throws Exception{
//更新语句......
int cnt = iUserDao.updateUser(newvalue, conds);
if(cnt > 0) {
throw new RuntimeException(); ---------(3)
}
}
注意一:第(3)处替换为“throw new FileNotFoundException();”或者“throw new Exception();”,(1)(2)均执行成功,并抛出相应的异常!
注意二:若在函数public int updateUser(User user) throws Exception加上“@Transactional(rollbackFor = Exception.class)”,执行结果同上,因为@Transactional默认的传播是:Propagation.REQUIRED,即表明当前如果有事务, 那么加入事务, 没有的话新建一个,当前是有事务的,不用新建,也即是说“@Transactional(rollbackFor = Exception.class)”不起任何作用。
Case 2:(1)和(2)处均执行不成功,并抛出java.lang.RuntimeException异常
类UserServiceImpl:
public class UserServiceImpl implements IUserService {
@Resource
IUser2Service iUser2Service;
@Resource(name = "userDao")
IUserDao iUserDao;
@Transactional
public void testModifyUser(User user) throws Exception {
int num = iUserDao.insertUser(user); -------(1)
System.out.println("effect " + num + " rows!");
B(); -------(2)
}
// 私有方法
private void B() throws Exception {
iUser2Service.deleteUserById(25);
}
//......
}
类User2ServiceImpl:
@Service
public class User2ServiceImpl implements IUser2Service {
@Resource(name = "userDao")
IUserDao iUserDao;
@Transactional -------------------------(3)
public int deleteUserById(int id) throws Exception {
Map<String, Object> conds = Maps.newHashMap();
conds.put("id", id);
int cnt = iUserDao.deleteUserById(conds);
if(cnt > 0) {
throw new RuntimeException(); ---------------------(4)
}
return cnt;
}
}
注意:情况一:第(4)处替换为“throw new FileNotFoundException();”或者“throw new Exception();”,(1)(2)均执行成功,并抛出相应的异常!
情况二:第(3)处去掉“@Transactional”,即不加事务,(1)和(2)处均执行不成功,并抛出java.lang.RuntimeException异常!
情况三:第(3)处去掉“@Transactional”,同时第(4)处替换为“throw new FileNotFoundException();”或者“throw new Exception();”,则(1)(2)均执行成功,并抛出相应的异常!
情况四:第(3)处替换为“@Transactional(rollbackFor = Exception.class)”,(1)和(2)处均执行不成功,并抛出java.lang.RuntimeException异常!
情况五:第(3)处替换为“@Transactional(rollbackFor = Exception.class)”,同时第(4)处替换为“throw new FileNotFoundException();”或者“throw new Exception();”,则(1)(2)均执行失败,并抛出相应的异常,同时抛出“org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only”异常!