Spring--事务管理

1. Spring中事务的管理

1.1 为什么要使用spring

可以保证数据的完整性。

例子: 转账为例。

张三向李四转账1000元。----再数据库中修改两个账号的余额。

发生意外情况,

出现金庸减钱成功,而张无忌加钱失败。

如何解决?

使用事务解决问题 

此时代码执行后金庸的钱没有减,张无忌的钱也没有加,问题完美解决! nice

疑惑: 明明第一条语句已经执行成功,为什么没有减钱呢 

数据库事务的原理 如果不写begin;commit;此时事务默认自动开启,自动提交; 在数据库中 ,事务都是自动提交的。事务的自动提交就是 执行sql语句完成之后 就立 刻持久化到 数据库中。

begin;开始事务

rollback;回滚事务

commit;提交事务

当我们添加了begin;和commit后 事务的提交就从自动变成手动。因为中 途出错,所以导致 commit不执行,也就是说缓冲区中的数据没有持久化 的数据库中 。

代码演示:

package com.qy151;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @program: transaction-qy151
* @description:
* @author: YSH
* @create: 2022-07-08 14:38
* 默认jdbc 事务也是自动提交
**/
public class Test {
    public static void main(String[] args) {
    Connection connection =null;
    try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        connection= DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai",
                    "root",
                    "root"
        );
        connection.setAutoCommit(false);//开启事务的
        手动提交
        String sql = "update tb_emp set
        salary=salary-1000 where name='金庸'";
        PreparedStatement ps =connection.prepareStatement(sql);
        ps.executeUpdate();
        String sql1 = "update tb_emp set salary=salary+1000 where name='张无忌'";
        ps = connection.prepareStatement(sql1);
        ps.executeUpdate();
        connection.commit();//提交事务
        }catch (Exception e){
    try {
            connection.rollback();//事务回滚 最初的状态
        } catch (SQLException throwables) {
            throwables.printStackTrace();
    }
        e.printStackTrace();
}finally{
        }
    }
}

1.2 什么是事务? 

从开启到提交为一个事务。 由此可见,一个事务对应一组业务。一个事务 中间可以有一条sql,多条sql。 所以 一个业务开始之前 开启事务 一个业务 结束之后 提交事务。 我们这个转账案例:需要几个事务? 可以写成两个 事务,但是不合适。因为我们的需求 让张三减的同时让李四加钱。只能写 成一个事 务。 把多条sql语句当作一件事情,要同时都能执行到。

事务(Transaction),一般是指要做的或所做的事情。在计算机术语 中是指访问并可能更新数据库中各种数据项的一个程序执行单元 (unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或 Java)书写的用户程序的执行所引起,并用形如begin transaction和 end transaction语句(或函数调用)来界定。事务由事务开始 (begin transaction)和事务结束(end transaction)之间执行的全体 操作组成。 概括为: 事务是由一些列动作组成,这些动作要么都执行,要么都不执 行。

1.3 事务的特性:ACID 

 1、原子性(Atomicity): 事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间 环节。事务执行过程中 出错,会回滚到事务开始前的状态,所有的操作就 像没有发生一样。也就是说事务是一个不可分 割的整体,就像化学中学过 的原子,是物质构成的基本单位。

2、一致性(Consistency): 事务开始前和结束后,数据库的数据完整性约束没有被破坏,事务前后操 作数据是一致的 。比如 A向B转账,不可能A扣了钱,B却没收到。 能量守恒。

3、隔离性(Isolation): 一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数 据对并发的其他事务是 隔离的,并发执行的各个事务之间不能互相干扰。 比如A正在从一张银行卡中取钱,在A取钱的过 程结束前,B不能向这张卡 转账。 两个事务之间是有隔离级别,隔离级别的不同会导致出现不同的问 题。此时产生三种读: 脏读 幻读 不可重复读。

4、持久性(Durability): 持久性(durability)。持久性也称永久性(permanence),指一个事务 一旦提交,它对数据库 中数据的改变就应该是永久性的。接下来的其他操 作或故障不应该对其有任何影响。

1.4 事务的并发问题

1、脏读:

事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

场景:公司发工资了,领导把5000元打到Tom的账号上,但是该事务并未提交,而Tom正好去查看账户,发现工资已经到账,账户多了5000元,非常高兴,可是不幸的是,领导发现发给Tom的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,Tom再次查看账户时发现账户只多了2000元,Tom空欢喜一场,从此郁郁寡欢,走上了不归路.....

2、不可重复读:


事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。


场景:Tom拿着工资卡去消费,酒足饭饱后在收银台买单,服务员告诉他本次消费1000元,Tom将银行卡给服务员,服务员将银行卡插入POS机,POS机读到卡里余额为3000元,就在Tom磨磨蹭蹭输入密码时,他老婆以迅雷不及掩耳盗铃之势把Tom工资卡的3000元转到自己账户并提交了事务,当Tom输完密码并点击"确认"按钮后,POS机检查到Tom的工资卡已经没有钱,扣款失败,Tom十分纳闷,明明卡里有钱,于是怀疑POS有鬼,和收银小姐姐大打出手,300回合之后终因伤势过重而住进ICu,Tom从此郁郁寡欢,从此走上了不归路....


分析:上述情况即为不可重复读,两个并发的事务;

“事务A:POS机扣款"、

“事务B:Tom的老婆网上转账",

事务A事先读取了数据,事务B紧接了更新数据并提交了事务,而事务A再次读取该数据扣款

不可重复读操作的是同一条数据,而且做的是修改操作 

3、幻读:


已知有两个事务A和B,A从一个表中读取了数据,然后B在该表中插入了一些新数据,导致A再次读取同一个表,就会多出几行,简单地说,一个事务中先后读取一个范围的记录,但每次读取的纪录数不同,称之为幻象读


场景:Tom跟朋友聚餐完毕后开启事务付账,先付了80元烟钱,Tom的老婆正好在家里查账发现Tom仅仅有80元的消费记录,非常吃惊,心想“老公真是太节俭了,嫁给他真好! ”,而Tom此时再次支付饭钱1000元,即新增了一条1000元的消费记录并提交了事务,沉浸在幸福中的老婆不敢相信自己的眼睛,又查询了Tom当天工资卡消费明细,一探究竟,可查出的结果竟然发现又多了一笔1000元的消费,Tom的老婆瞬间怒气冲天,外卖订购了一个大号的榴莲,傍晚降临,Tom生活在了水深火热之中,只感到膝盖针扎的痛.....


小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

 

 

1.5隔离级别

解决上面事务并发带来的问题

级别越高,效率越低;mysql的默认隔离级别是可重复读

mysql如何查看隔离级别以及设置隔离级别:

2.Spring如何支持事务

思考:业务功能包含多个操作,[我们可以使用事务来管理]

spring如何支持事务的呢?---

思考:事务管理加在那一层?service层

 

1.加入aspect,tx依赖 

    <!--aop 面向切面编程 切面依赖-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aspects</artifactId>
          <version>5.2.15.RELEASE</version>
      </dependency>
      <!--spring的事务依赖-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
          <version>5.2.15.RELEASE</version>
      </dependency>

2.spring配置事务管理类开启事务注解

    <!--创建spring事务管理类-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="DataSource"/>
    </bean>
 
    <!--开启事务注解-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
spring-data-redis 1.6.0 是一个用于与 Redis 数据库进行交互的开源框架。它是 Spring Data 项目的一部分,提供了方便的 API 以简化对 Redis 数据库的访问。 spring-data-redis 1.6.0 提供了与 Redis 的完整集成,包括连接管理、数据存储和检索、事务管理、缓存支持等功能。 在连接管理方面,spring-data-redis 1.6.0 支持连接池和 Redis Sentinel 的自动探测和故障转移。它使用 Jedis 或 Lettuce 作为 Redis 客户端,并提供了一致的、可靠的连接管理机制。 在数据存储和检索方面,spring-data-redis 1.6.0 提供了多种方式来操作 Redis 数据库。它支持存储和检索各种数据结构,例如字符串、哈希、列表、集合和有序集合。它还支持基于时间的键过期和发布-订阅模式。 在事务管理方面,spring-data-redis 1.6.0 支持 Redis 的事务。它通过与 Spring 的事务管理器集成,实现了对 Redis 的事务操作的支持。这样,我们可以在 Spring 事务管理下执行 Redis 的多个操作,保证它们的原子性。 在缓存支持方面,spring-data-redis 1.6.0 提供了对 Redis 缓存的支持。我们可以使用注解方式将方法的返回值缓存到 Redis 数据库中,以提高系统的性能和响应速度。 总之,spring-data-redis 1.6.0 是一个功能强大、易于使用的框架,为我们提供了与 Redis 数据库进行交互的便捷方式。它可以极大地简化我们对 Redis 数据的存储和检索,提供了灵活而高效的数据操作方式。同时,它与 Spring 框架的无缝集成,使我们能够更好地利用 Redis 在我们的应用程序中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值