美文网首页Spring框架深入浅出
Spring 的事务传播类型、事务隔离级别

Spring 的事务传播类型、事务隔离级别

作者: 锕123 | 来源:发表于2018-09-29 11:09 被阅读0次

事务传播类型

spring 的7种事务传播类型

  • PROPAGATION_REQUIRED: 如果当前没有事务,则创建一个新事务;如果当前存在事务,就加入该事务;该配置是最常用的设置。
  • PROPAGATION_SUPPORTS: 支持当前事务,如果当前存在事务则加入该事务;如果当前不存在事务,就以非事务执行。
  • PROPAGATION_MANDATORY: 支持当前事务,如果当前存在事务则就加入该事务;如果不存在事务,则抛出异常。
  • PROPAGATION_REQUIRES_NEW: 无论当前存在不存在事务,都创建新事务。
  • PROPAGATION_NOT_SUPPORTED: 以非事务方式执行操作,如果当前存在事务,则把当前事务挂起。
  • PROPAGATION_NEVER: 以非事务方式执行,如果当前存在事务,则抛出异常。
  • PROPAGATION_NESTED: 如果当前存在事务,则在嵌套事务内执行,如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

注意:
内部方法直接调用,传播性失效

@Service("studentImpl")
public class StudentImpl implements Student {
 
    @Autowired
    StudentDao studentDao;
    
    @Autowired
    UserService userService;
 
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
    public String doA() throws Exception {
        Student student = new Student();
        student.setSex("F");
        student.setUsername("唐玄奘");
        studentDao.insertStudent(student);
        
        
        userService.addUser();
        int i = 1 / 0; // 模拟异常,事务回滚
        return "ok!";
    }
 
}
@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
  
    @Autowired
    UserDao userDao;
    
    @Transactional(propagation = Propagation.REQUIRES_NEW,isolation=Isolation.DEFAULT,rollbackFor=Exception.class)  
    public String addUser() throws Exception {
        User user = new User();
        user.setUsername("观世音菩萨");
        userDao.insert(user);
        return "ok!";
    }
     
}

结果:只会是 user 插入成功, 因为 addUser方法使用了事务传播行为:Propagation.REQUIRES_NEW,当前存在事务1,则新建了一个自己的事务,并挂起了事务1. 事务2提交后,事务1由于抛出了异常回滚。

如果以上例子改为在一个方法中调用另一个事务方法,另一个方法的传播行为会失效:

@Service("studentImpl")
public class StudentImpl implements Student {
 
    @Autowired
    StudentDao studentDao;
    
    @Autowired
    UserDao userDao;
 
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
    public String doA() throws Exception {
        Student student = new Student();
        student.setSex("F");
        student.setUsername("唐玄奘");
        studentDao.insertStudent(student);
        
        
        userService.addUser();
        int i = 1 / 0; // 模拟异常,事务回滚
        return "ok!";
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW,isolation=Isolation.DEFAULT,rollbackFor=Exception.class)  
    public String addUser() throws Exception {
        User user = new User();
        user.setUsername("观世音菩萨");
        userDao.insert(user);
        return "ok!";
    }
 
}


结果:addUser 的事务传播性会失效,事务1回滚后,数据库不会插入任何记录。

spring 的5种隔离级别

  • ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。
  • ISOLATION_READ_UNCOMMITTED: 事务最低的隔离级别,它允许其他事务可以看到这个事务未提交的数据;会产生脏读、不可重复读、幻读。
  • ISOLATION_READ_COMMITTED: 保证一个事务提交后才能被另一个事务读取;另外一个事务不能读取该事务未提交的数据;这种事务隔离级别可以避免脏读出现,但是可能会出现 不可重复读、幻读。
  • ISOLATION_REPEATABLE_READ: 防止出现脏读、不可重复读,但是可能出现幻读;一个事务不能读取另一个事务未提交的数据,同时避免出现 不可重复读。
  • ISOLATION_SERIALIZABLE: 防止脏读、不可重复读、幻读;代价最高可靠性最好的事务隔离级别,事务被处理为顺序执行。

关键词:

幻读: 事务1 读取记录时,事务2 增加了记录并提交, 事务1 再次读取时可以看到事务2 新增的记录。 指一个事务读取了一个未提交事务的数据。

不可重复读取: 事务1 读取记录时, 事务2 更新了记录并提交, 事务1 再次读取时可以看到 事务2 修改后的记录。 在一个事务内读取表中的某一行数据,多次读取结果不同,一个事务读取到了另一个事务提交后的数据。

脏读: 事务1 更新了记录, 但是没有提交,事务2 读取了更新后的行, 然后事务1 回滚,现在事务2 读取无效。 在一个事务内读取了别的事务插入的数据,导致前后读取不一致。

相关文章

网友评论

    本文标题:Spring 的事务传播类型、事务隔离级别

    本文链接:https://www.haomeiwen.com/subject/kfuvoftx.html