Java中使用事务(注解实现)
事务的介绍
描述: 对于一个功能实现或者业务流程,要么全做,要么全不做!
 特性: ACID
- A - 原子性:执行的最小单位,要么全做,要么全不做。(undo-log保证)
 - C - 一致性:事务执行前后,数据库中的数据保持一致。(不一致:丢失修改、脏读、不可重复读、幻读)
 - I - 隔离性:多个并发的事物之间是相互隔离的。
 - D - 持久性:事务对数据的修改是永久性的。(redo-log保证)
 
第一步: 引入依赖
<!-- 项目启动依赖 @Service @Component @RestController tomcat等等 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
第二步:Java代码
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class HelperService {
    @Resource
    private TaskDao taskDao;
    @Resource
    private TaskDetailDao taskDetailDao;
    // isolation:事务的隔离级别,此处使用后端数据库的默认隔离级别, propagation: 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中(常见)。
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
    public void test(Task task, TaskDetail taskDetail){
        taskDao.saveTask(task);
        int a = 3 / 0;
        taskDetailDao.saveTaskDetail(taskDetail);
    }
}
补充事务的传播行为
 
 常用的事务传播行为: Propagation.REQUIRED或者Propagation.REQUIRES_NEW
补充事务的隔离级别
 (1)DEFAULT
   使用数据库设置的隔离级别(默认),由DBA 默认的设置来决定隔离级别。
 (2)READ_UNCOMMITTED
   这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。
   会出现脏读、不可重复读、幻读 (隔离级别最低,并发性能高)。
 (3)READ_COMMITTED
   保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
   可以避免脏读,但会出现不可重复读、幻读问题(锁定正在读取的行)。
 (4)REPEATABLE_READ(innodb默认的数据库隔离级别)
   可以防止脏读、不可重复读,但会出幻读(锁定所读取的所有行)。
 (5)SERIALIZABLE
   这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。
   保证所有的情况不会发生(锁表)。
   
 注意:myisam与innodb的区别!
- myisam只有表级锁,innodb可以支持表级锁和行级锁(默认行级锁)。
 - myisam强调查询性能,查询操作比innodb快,但是不提供事务支持。innodb提供事务、外键等高级功能,同时具有事务、回滚、崩溃修复能力。
 - myisam不支持外键,innodb支持外键。
 - MVCC支持:仅有innodb支持MVCC,同时MVCC只在READ_COMMITTED和REPEATABLE_READ这两个隔离级别下工作。【MVCC:多版本并发控制,使不同事务的读写操作并发执行,提升系统性能。】
 
第三部: 启动类增加注解
注意一定要启动类开启注解
// 开启注解
@EnableTransactionManagement
补充:事务失效的常见原因
1、 @Transactional必须作用于public方法之上;
 2、 @Transactional注解的属性rollbackFor 配置错误,默认只有RuntimeException才会回滚;
 3、 启动类没有添加@EnableTransactionManagement
 4、 同一个类中调用事务方法,事务会失效。
@Service
public class A{
	public void test01(){
	// do something
	test02();
	// do something
	}
	@Transactional(rollbackFor = Exception.class, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
	public void test02(){
	// do something (操作多个表的增删改)
	}
	
}
5、 异常被捕获了:在事务方法中捕获了异常,事务会失效;
 6、 数据库引擎不支持事务;(常见数据库引擎:innodb、bdb支持事务,myisam不支持数据)
