设为首页 加入收藏

TOP

14、Spring之基于注解的声明式事务(四)
2023-09-09 10:25:58 】 浏览:85
Tags:Spring 于注解 明式事

此时id为1的用户余额为0,少了50(一本图书价格为50)

14.5.4、隔离级别

14.5.4.1、使用目的

  • 数据库系统具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题

  • 一个事务与其他事务隔离的程度,称为隔离级别

  • SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度

  • 隔离级别越高,数据一致性就越好,但并发性越弱

隔离级别一共有四种:

  • 读未提交(READ UNCOMMITTED):允许Transaction01读取Transaction02未提交的修改

  • 读已提交(READ COMMITTED):要求Transaction01只能读取Transaction02已提交的修改

  • 可重复读(REPEATABLE READ):确保Transaction01可以多次从一个字段中读取到相同的值;
    即Transaction01执行期间禁止其它事务对这个字段进行更新

  • 串行化(SERIALIZABLE):确保Transaction01可以多次从一个表中读取到相同的行;
    在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作;
    该隔离级别可以避免任何并发问题,但性能十分低下

各个隔离级别解决并发问题的能力见下表:

隔离级别 脏读 不可重复读 幻读
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE
  • 脏读(DirtyRead):一个事务读取了另一个并行未提交事务写入的数据。

  • 不可重复读(Non-RepeatableRead):一个事务重新读取之前读取过的数据,
    发现该数据已经被另一个事务(在初始读之后提交)修改。

  • 幻读(PhantomRead):一个事务重新执行一个返回符合一个搜索条件的行集合的查询,
    发现满足条件的行集合因为另一个最近提交的事务而发生了改变。

各种数据库产品对事务隔离级别的支持程度:

隔离级别 Oracle MySQL SQL Server 达梦 人大金仓
READ UNCOMMITTED × ×
READ COMMITTED √(默认) √(默认) √(默认) √(默认)
REPEATABLE READ × √(默认) ×
SERIALIZABLE

14.5.4.2、使用方式

@Transactional(isolation = Isolation.DEFAULT)//使用数据库默认的隔离级别(默认且常用)
@Transactional(isolation = Isolation.READ_UNCOMMITTED)//读未提交
@Transactional(isolation = Isolation.READ_COMMITTED)//读已提交
@Transactional(isolation = Isolation.REPEATABLE_READ)//可重复读
@Transactional(isolation = Isolation.SERIALIZABLE)//串行化

14.5.5、传播行为

14.5.5.1、使用目的

当事务方法被另一个事务方法调用时,需要指定事务应该如何传播

14.5.5.1.1、创建结账业务层接口CheckoutService及其实现类

image

package org.rain.spring.service;

/**
 * @author liaojy
 * @date 2023/8/29 - 8:07
 */
public interface CheckoutService {

    void checkout(Integer[] bookIds, Integer userId);

}

image

注意:checkout方法进行了事务管理,它调用的buyBook方法也进行了事务管理

package org.rain.spring.service.impl;

import org.rain.spring.service.BookService;
import org.rain.spring.service.CheckoutService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author liaojy
 * @date 2023/8/29 - 8:10
 */
@Service
public class CheckoutServiceImpl implements CheckoutService {

    @Autowired
    private BookService bookService;

    //一次购买多本图书
    @Transactional
    public void checkout(Integer[] bookIds, Integer userId) {
        for (Integer bookId : bookIds) {
            bookService.buyBook(bookId,userId);
        }
    }

}
14.5.5.1.2、在控制层BookController中添加结账方法

image

    @Autowired
    private CheckoutService checkoutService;

    public void checkout(Integer[] bookIds, Integer userId){
        checkoutService.checkout(bookIds, userId);
    }
14.5.5.1.3、添加结账的测试方法

image

    @Test
    public void testCheckout(){
        Integer[] bookIds = {1,2};
        bookController.checkout(bookIds,1);
    }
14.5.5.1.4、执行结账前的数据

image

此时id为1的图书(价格为80)库存为100,id为2的图书(价格为50)库存为100

image

此时id为1的用户余额为100

14.5.5.1.5、执行结账时的异常

image

14.5.5.1.6、执行结账后的数据

image

此时id为1的图书(价格为80)库存为100,id为2的图书(价格为50)库存为100;库存没有变化

image

此时id为1的用户余额为100;余额没有变化

14.5.5.1.7、测试的数据结果分析
  • @Transactional注解的propagation属性的默认值为:Propagation.REQUIRED;
    表示如果有已经开启的事务可用,那么就在这个事务中运行。

  • 经过观察,购买图书的方法buyBook()在checkout()中被调用,checkout()上有事务注解,因此在此事务中执行。

  • 所购买的两本图书的价格为80和50,而用户的余额为100;
    因此在购买第二本图书时余额不足失败,导

首页 上一页 1 2 3 4 5 下一页 尾页 4/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java - ThreadPoolExecutor线程池.. 下一篇集群部署专题之二:超高性能RPC框..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目