Spring中的事务

发布于:2024-06-01 ⋅ 阅读:(136) ⋅ 点赞:(0)

目录

一.什么是事务?

二.事务的操作

三.Spring 中事务的实现

1.Spring 编程式事务(手动操作)

2.Spring 声明式事务

四.事务隔离级别

1.MySQL 事务隔离级别

2.Spring 事务隔离级别

五.Spring 事务传播机制


一.什么是事务?

事务是指作为单个逻辑工作单元执行的一系列操作,这些操作要么全部成功完成,要么全部失败回滚。在数据库系统中,事务是确保数据完整性和一致性的重要概念。

事务具有以下四个特性,通常被简称为 ACID 特性:

  1. 原子性(Atomicity):事务是一个原子操作单元,不可分割。这意味着事务中的所有操作要么全部提交成功,要么全部失败回滚,不存在部分操作成功部分操作失败的情况。

  2. 一致性(Consistency):事务执行前后,数据应该保持一致状态。如果事务执行失败,则系统应该回滚到事务执行前的状态,保证数据的一致性。

  3. 隔离性(Isolation):多个事务同时执行时,每个事务的操作应该与其他事务隔离开来,互不影响。这样可以防止并发执行时出现数据不一致的情况。

  4. 持久性(Durability):一旦事务提交成功,其对数据库的修改应该是永久性的,即使系统发生故障也不会丢失提交的数据。

在数据库系统中,通过事务可以将一系列数据库操作组合成一个逻辑单元,确保这些操作要么全部成功执行,要么全部失败回滚,从而保证数据的完整性和一致性。事务可以通过事务管理器来实现,常见的事务管理器包括数据库本身提供的事务支持以及应用程序框架(如Spring)提供的事务管理功能,而本文章就主要讲解Spring中提供的事务管理功能

二.事务的操作

事务的操作主要有三步:

  1.  开启事start transaction/ begin (⼀组操作前开启事务)
  2.  提交事务: commit (这组操作全部成功, 提交事务)
  3.  回滚事务: rollback (这组操作中间任何⼀个操作出现异常, 回滚事务)

三.Spring 中事务的实现

1.Spring 编程式事务(手动操作)

首先要认识spring中的两个对象:

  • DataSourceTransactionManager 事务管理器. ⽤来获取事务(开启事务), 提交或回滚事务
  • TransactionDefinition 事务的属性, 在获取事务的时候需要将 TransactionDefinition 传递进去来获得⼀个事务 TransactionStatus

示例如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;

public class TransactionalService {

    @Autowired
    private DataSourceTransactionManager transactionManager;

    public void performTransactionalOperation() {
        // 定义事务属性
        TransactionDefinition def = new DefaultTransactionDefinition();
        // 开始事务
        TransactionStatus status = transactionManager.getTransaction(def);
        try {
            // 执行业务逻辑,例如插入数据
            jdbcTemplate.update("INSERT INTO table_name (column1, column2) VALUES (?, ?)", value1, value2);

            // 提交事务
            transactionManager.commit(status);
        } catch (Exception ex) {
            // 出现异常,回滚事务
            transactionManager.rollback(status);
            throw ex;
        }
    }
}

在上述代码中,我们首先自动注入一个DataSourceTransactionManager 事务管理器,然后在方法中定义了一个事务的属性 def 并将 def 传入 dataSourceTransactionManager来开启事务,接着就可以执行业务的逻辑,如果正常完成就提交事务,捕获到异常就回滚事务

2.Spring 声明式事务

声明式事务的实现很简单, 只需要在需要事务的方法上添加 @Transactional 注解就可以实现了.无需手动开启事务和提交事务, 进入方法时自动开启事务, 方法执行完会自动提交事务, 如果中途发⽣了 没有处理的异常会⾃动回滚事务.

示例如下:

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class TransactionalService {
    
    @Transactional
    public void performTransactionalOperation() {
        // 执行需要事务管理的业务逻辑
    }
}

下面是@Transactional注解的一些常用属性和用法:

  • 属性

    • propagation:事务的传播行为,指定事务的传播方式,如REQUIRED、REQUIRES_NEW等。
    • isolation:事务的隔离级别,指定事务的隔离级别,如READ_COMMITTED、SERIALIZABLE等。
    • timeout:事务超时时间,指定事务的超时时间,单位为秒。
    • readOnly:只读事务,指定事务是否为只读事务,可以优化性能。
    • rollbackFor:指定哪些异常会导致事务回滚。
    • noRollbackFor:指定哪些异常不会导致事务回滚。
  • 用法

    • 在类级别上添加@Transactional注解:表示该类中所有public方法都需要进行事务管理。
    • 在方法级别上添加@Transactional注解:表示该public方法需要进行事务管理,优先级高于类级别的注解。
    • 注解可以放在接口、类、方法等地方,Spring会根据AOP的代理机制为被注解的方法生成事务管理的代理。

注意:@Transactional 默认只在遇到运行时异常和Error时才会回滚, 非运行时异常不回滚. 如果我们需要所有异常都回滚, 需要来配置 @Transactional 注解当中的 rollbackFor 属性, 通过rollbackFor 这个属性指定出现何种异常类型时事务进行回滚

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class TransactionalService {
    
    @Transactional(rollbackFor = Exception.class)
    public void performTransactionalOperation() {
        // 执行需要事务管理的业务逻辑
    }
}

四.事务隔离级别

1.MySQL 事务隔离级别

MySQL 提供了多种事务隔离级别,用于控制并发事务执行时所遇到的问题。事务隔离级别定义了一个事务内部对其他事务的可见性以及并发读写操作的规则。以下是 MySQL 中常见的事务隔离级别:

1. 读未提交(Read Uncommitted)
   - 在该隔离级别下,事务中的修改会立即对其他事务可见,即使这些修改尚未被提交。这可能导致脏读(读取了未提交的数据)和不可重复读(同一查询在多次执行过程中返回不同的结果)。

2. 读提交(Read Committed)
   - 在该隔禅级别下,事务只能看见已经提交的数据,这可以避免脏读,但是依然可能出现不可重复读的问题。

3. 可重复读(Repeatable Read)
   - 在该隔离级别下,事务开始时读取的数据集是固定的,即使其他事务对数据进行了修改或者插入。这可以避免脏读和不可重复读,但可能出现幻读(一个事务在前后两次查询同样的条件,得到了不一样的结果)。

4. 序列化(Serializable)
   - 在该隔离级别下,事务顺序执行,事务之间彼此不会产生影响,可以避免脏读、不可重复读和幻读,但是性能较差,因为所有的并发事务都需要按顺序执行。

在 MySQL 中,默认的事务隔离级别是可重复读(Repeatable Read)。

2.Spring 事务隔离级别

Spring 事务管理器提供了与数据库事务隔离级别相对应的事务隔离选项。Spring 框架通过使用底层数据库的事务隔离级别来控制事务的隔离性。以下是 Spring 中支持的事务隔离级别:

  1. DEFAULT

    • 使用底层数据库的默认隔离级别,通常是数据库的默认隔离级别。
  2. READ_UNCOMMITTED

    • 读未提交隔离级别,与数据库的读未提交(Read Uncommitted)隔离级别相对应。
  3. READ_COMMITTED

    • 读已提交隔离级别,与数据库的读提交(Read Committed)隔离级别相对应。
  4. REPEATABLE_READ

    • 可重复读隔离级别,与数据库的可重复读(Repeatable Read)隔离级别相对应。
  5. SERIALIZABLE

    • 序列化隔离级别,与数据库的序列化(Serializable)隔离级别相对应。

你可以通过在 @Transactional 注解中设置 isolation 属性来指定事务的隔离级别.

示例如下:

@Transactional(isolation = Isolation.READ_COMMITTED)
public void myTransactionalMethod() {
    // 事务操作...
}

五.Spring 事务传播机制

Spring 的事务传播机制定义了在多个事务方法之间如何传播事务的行为。当一个事务方法调用另一个事务方法时,Spring 可以根据定义的事务传播行为来处理事务的边界。以下是 Spring 中常见的事务传播行为:

  1. REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认的传播行为。

  2. SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。

  3. MANDATORY:必须在一个事务中执行,如果当前没有事务,则抛出异常。

  4. REQUIRES_NEW:创建一个新的事务,并在它自己的事务中执行。如果当前存在事务,则将其挂起。

  5. NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则将其挂起。

  6. NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。

  7. NESTED:如果当前存在事务,则在嵌套事务中执行;如果当前没有事务,则执行类似于 REQUIRED 的操作。嵌套事务是相对于外部事务的一个独立的事务,但是它们可以利用外部事务的事务属性。

可以在 @Transactional 注解中使用 propagation 属性来指定事务传播行为

示例如下:

@Transactional(propagation = Propagation.REQUIRED)
public void myTransactionalMethod() {
    // 事务操作...
}

关于Spring中事务的介绍到这就结束了~


网站公告

今日签到

点亮在社区的每一天
去签到