图解事务

1 理解事务

  • 一组sql语句(insert、update、delete),全部成功整体才算成功,一个失败整体也算失败。
  • 举例: 转账 a给b转账100元,a 和 b的账户中都有1000元, 转账完成后会是什么结果?
  • 使用sql语句描述上述过程:
  • 准备工作:
  • 财务表 t_account , 里面有 姓名列 name 和 余额列 money。 a=1000, b=1000
  • 正常情况下:
update t_account set money = money -100 where name='a';
update t_account set money = money +100 where name='b';
结果: a=900; b=1100
  • 异常情况下:
update t_account set money = money -100 where name='a';

发生异常;

update t_account set money = money +100 where name='b';


结果: a=900; b=1000
  • 思考: 这种结果合理吗?如果在你的身上发生这样的事 你可以容忍吗?
  • 如果出现了异常,怎么才算是合理的结果呢?
  • 是不是两个操作 要么全成功,要么全失败?
  • 事务的出现 解决上面的问题。 特点:要么全成功,要么全失败。
  • 事务是如何处理异常情况的呢?
  • 开启事务 (针对一组sql) a=1000 b=1000
update t_account set money = money -100 where name='a'; -- a=900;

发生异常; 进行事务管理 -- 事务回滚 -- 撤销修改操作: -- a=1000;

update t_account set money = money +100 where name='b';

结果: a=1000  b=1000
  • 事务是如何处理正常情况的呢?
开启事务

update t_account set money = money -100 where name='a'; a=900update t_account set money = money +100 where name='b';   b=1100

提交事务,使更改的内容生效。


结果:a=900        b=1100
  • 简单总结:
    在这里插入图片描述
开启事务
执行sql语句群
出现异常 回滚事务(撤销)一切正常 事务提交(生效)

2 Mysql中的事务管理

  • mysql 的事务 默认 自动打开,自动提交。 一条sql就是一个事务,所以不需要 事务开启、事务回滚、事务提交。
开启事务: start transaction;
执行sql语句群
出现异常 事务回滚(撤销)事务结束 rollback;无异常 事务提交(生效) 事务结束 commit;
start transaction;  --- 开启事务。以后的sql都在一个事务中。更改的内容不会自动提交。

rollback;  --- 回滚事务,都失败的情况。事务结束,全部失败,数据恢复到事务未开启之前的状态。

commit; --- 提交事务,都成功的情况。事务结束,全部成功。

在这里插入图片描述

  • 准备工作:
create table account(
    name varchar(32),
    money int
);

insert into account values('a', 1000);
insert into account values('b', 1000);

需求1:演示事务回滚

在这里插入图片描述

需求2:演示事务提交

在这里插入图片描述

3 java中的事务管理

开启事务: Connection.setAutoCommit(false)
执行sql语句群
出现异常 事务回滚(撤销)事务结束 Connection.rollback();无异常 事务提交(生效)事务结束 Connection.commit();

3.1 演示未添加事务

  • 需求:a 向 b 转账 100元。(未添加事务)
@Test
public void demo1() {
    // 需求:a 向 b 转账 100元。(未添加事务)
    Connection conn = null;
    PreparedStatement stmt = null;

    try {
        // 获取连接
        conn = JDBCUtils.getConnection();

        // a-100
        // 获得发送sql的对象
        String sql = "update account set money=money-100 where name='a'";
        stmt = conn.prepareStatement(sql);
        // 发送sql 获得结果
        stmt.executeUpdate();

        // b+100
        // 获得发送sql的对象
        String sql2 = "update account set money=money+100 where name='b'";
        stmt = conn.prepareStatement(sql2);
        // 发送sql 获得结果
        stmt.executeUpdate();

        System.out.println("一切ok");
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("出现异常");
    } finally {
        JDBCUtils.release(conn, stmt);
    }
}

3.2 演示添加事务

  • 需求:a 向 b 转账 100元, 模拟异常。(强调事务的重要性:要么全执行,要么全撤销。)
 @Test
    public void demo2() {
        // 需求:a 向 b 转账 100元, 模拟异常。(强调事务的重要性:要么全执行,要么全撤销。)
        Connection conn = null;
        PreparedStatement stmt = null;

        try {
            // int j = 1 / 0;
            // 获取连接
            conn = JDBCUtils.getConnection();
            // 开启事务
            conn.setAutoCommit(false);

            // a-100
            // 获得发送sql的对象
            String sql = "update account set money=money-100 where name='a'";
            stmt = conn.prepareStatement(sql);
            // 发送sql 获得结果
            stmt.executeUpdate();

            // b+100
            // 获得发送sql的对象
            String sql2 = "update account set money=money+100 where name='b'";
            stmt = conn.prepareStatement(sql2);
            // 发送sql 获得结果
            stmt.executeUpdate();

            int j = 1 / 0;
            System.out.println("一切ok, 提交事务");
            conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("出现异常,回滚事务");
            try {
                if (conn != null) {
                    conn.rollback();
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        } finally {
            JDBCUtils.release(conn, stmt);
        }
    }
  • 注意事项
    • 1、Connection 和 PrepareStatement 对象引入时,必须是java.sql 包下的。
    • 2、开启事务 conn.setAutoCommit(false) 必须在 Connection对象获取之后。
    • 3、抓异常时,最好选得大一些。因为 数/0报的是 算术异常不在sql异常范围内,所以最好改成Exception。

3.3 DBUtils事务操作

Connection对象的方法名描述
conn.setAutoCommit(false)开启事务
new QueryRunner()创建核心类,不设置数据源(手动管理连接)
query(conn , sql , handler, params ) 或 update(conn, sql , params)手动传递连接, 执行SQL语句CRUD
DbUtils.commitAndCloseQuietly(conn)提交并关闭连接,不抛异常
DbUtils.rollbackAndCloseQuietly(conn)回滚并关闭连接,不抛异常
  • 代码演示
/*
DBUtils 的事务操作
 */
public class TransactionDemo2 {

    /*
    1.获得连接
    2.开始事务
    3.具体的sql操作(加钱, 减钱)
    4.提交事务 ,释放资源
    5.如果出现异常, 回滚事务释放资源
     */
    @Test
    public void test1() throws SQLException {
        Connection conn = null;
        try {
            //1.获得连接
            conn =  DruidUtils.getConnetion();
            // 2.开始事务
            conn.setAutoCommit(false);
            // 3.具体的sql操作(加钱, 减钱)
            QueryRunner qr = new QueryRunner();
            //减钱
            String sql = "update account set money=money-? where name=?";
            qr.update(conn, sql, 1000, "jack");
            //模拟错误
            int n =1/0;
            //加钱
            sql = "update account set money=money+? where name=?";
            qr.update(conn, sql, 1000, "rose");
            //4.提交事务 ,释放资源
            DbUtils.commitAndCloseQuietly(conn);
        } catch (Exception e) {
            e.printStackTrace();
            //5.如果出现异常, 回滚事务释放资源
            DbUtils.rollbackAndCloseQuietly(conn);
        }
    }
}

4 事务特性:ACID

  • 原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
  • 一致性(Consistency)事务前后数据的完整性必须保持一致,也就是说回滚前后数据一致
  • 隔离性(Isolation)事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
  • 持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

5 并发访问问题

  • 如果不考虑隔离性,事务存在3中并发访问问题。

脏读:一个事务读到了另一个事务未提交的数据.

不可重复读:一个事务读到了另一个事务已经提交(update)的数据。引发另一个事务,在事务中的多次查询结果不一致主要是数据内容

虚读 /幻读:一个事务读到了另一个事务已经提交(insert)的数据。导致另一个事务,在事务中多次查询的结果不一致主要是条数

6 隔离级别:解决问题

  • 数据库规范规定了4种隔离级别,分别用于描述两个事务并发所有情况

read uncommitted 读未提交,一个事务读到另一个事务没有提交的数据。

  • a)存在:3个问题(脏读、不可重复读、虚读)。
  • b)解决:0个问题

read committed 读已提交,一个事务读到另一个事务已经提交的数据。

  • a)存在:2个问题(不可重复读、虚读)。
  • b)解决:1个问题(脏读)

repeatable read:可重复读,在一个事务中读到的数据始终保持一致,无论另一个事务是否提交。

  • a)存在:1个问题(虚读)。
  • b)解决:2个问题(脏读、不可重复读)

serializable 串行化,同时只能执行一个事务,相当于事务中的单线程。

  • a)存在:0个问题。

  • b)解决:3个问题(脏读、不可重复读、虚读)

安全和性能对比

  • 安全性:serializable > repeatable read > read committed > read uncommitted
  • 性能 : serializable < repeatable read < read committed < read uncommitted
  • 也就是说两者不可兼得
  • 常见数据库的默认隔离级别:
    • MySql:repeatable read–可重复读,解决不可重复读和脏读
    • Oracle:read committed–读已提交,解决不可重复读

7 小结

  • 事务:逻辑上的一组sql操作,要么全执行,要么全不执行。
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数字乡村和智慧农业的数字化转型是当前农业发展的新趋势,旨在通过应用数字技术,实现农业全流程的再造和全生命周期的管理服务。中国政府高度重视这一领域的发展,提出“数字中国”和“乡村振兴”战略,以提升国家治理能力,推动城乡融合发展。 数字乡村的建设面临乡村治理、基础设施、产业链条和公共服务等方面的问题,需要分阶段实施《数字乡村发展战略纲要》来解决。农业数字化转型的需求包括满足市民对优质农产品的需求、解决产销对接问题、形成优质优价机制、提高农业劳动力素质、打破信息孤岛、提高农业政策服务的精准度和有效性,以及解决农业融资难的问题。 数字乡村建设的关键在于构建“1+3+4+1”工程,即以新技术、新要素、新商业、新农民、新文化、新农村为核心,推进数据融合,强化农业大数据的汇集功能。数字农业大数据解决方案以农业数字底图和数据资源为基础,通过可视化监管,实现区域农业的全面数字化管理。 数字农业大数据架构基于大数据、区块链、GIS和物联网技术,构建农业大数据中心、农业物联网平台和农村综合服务指挥决策平台三大基础平台。农业大数据中心汇聚各类涉农信息资源和业务数据,支持大数据应用。信息采集系统覆盖市、县、乡、村多级,形成高效的农业大数据信息采集体系。 农业物联网平台包括环境监测系统、视频监控系统、预警预报系统和智能控制系统,通过收集和监测数据,实现对农业环境和生产过程的智能化管理。综合服务指挥决策平台利用数据分析和GIS技术,为农业决策提供支持。 数字乡村建设包括三大服务平台:治理服务平台、民生服务平台和产业服务平台。治理服务平台通过大数据和AI技术,实现乡村治理的数字化;民生服务平台利用互联网技术,提供各类民生服务;产业服务平台融合政企关系,支持农业产业发展。 数字乡村的应用场景广泛,包括农业生产过程、农产品流通、农业管理和农村社会服务。农业生产管理系统利用AIoT技术,实现农业生产的标准化和智能化。农产品智慧流通管理系统和溯源管理系统提高流通效率和产品追溯能力。智慧农业管理通过互联网+农业,提升农业管理的科学性和效率。农村社会服务则通过数字化手段,提高农村地区的公共服务水平。 总体而言,数字乡村和智慧农业的建设,不仅能够提升农业生产效率和管理水平,还能够促进农村地区的社会经济发展,实现城乡融合发展,是推动中国农业现代化的重要途径。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值