Java中使用事务(注解实现)

事务的介绍

描述: 对于一个功能实现或者业务流程,要么全做,要么全不做!
特性: ACID

  1. A - 原子性:执行的最小单位,要么全做,要么全不做。(undo-log保证)
  2. C - 一致性:事务执行前后,数据库中的数据保持一致。(不一致:丢失修改、脏读、不可重复读、幻读)
  3. I - 隔离性:多个并发的事物之间是相互隔离的。
  4. 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的区别!

  1. myisam只有表级锁,innodb可以支持表级锁和行级锁(默认行级锁)。
  2. myisam强调查询性能,查询操作比innodb快,但是不提供事务支持。innodb提供事务、外键等高级功能,同时具有事务、回滚、崩溃修复能力。
  3. myisam不支持外键,innodb支持外键。
  4. 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不支持事务)

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐