JDBC总结——事务


事务

一、事务的基本介绍

1、概念

如果包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。

2、操作

  • ① 开启事务:start transaction;

  • ② 回滚:rollback;

  • ③ 提交:commit;

3、操作实例

account.sql

-- 创建account表
CREATE TABLE account(
	id INT PRIMARY KEY AUTO_INCREMENT;
	NAME VARCHAR(10),
	balance DOUBLE
);
-- 添加数据
INSERT INTO account (NAME,balance) VALUES ('zhangsan',1000),('lisi',1000);

SELECT * FROM account;
UPDATE account SET balance =1000;
--张三给李四转账500元

--0.开启事务
START TRANSACTION;
--1.张三账户-500
UPDATE account SET balance = balance - 500 WHERE NAME ='zhangsan';

--2.李四账户+500
UPDATE account SET balance = balance + 500 WHERE NAME = 'lisi';
--发现执行没有问题,提交事务
COMMIT;

--发现出现问题,回滚事务
ROLLBACK;

4、MySQL数据库中默认自动提交

事务提交的两种方式
1)自动提交

  • mysql是自动提交的
  • 一条DML(增删改)语句会自动提交一次事务

2)手动提交

  • Oracle 数据库默认是手动提交事务
  • 需要先开启事务,然后手动提交

修改事务的默认提价方式

  • 查看事务的默认提交方式:SElECT @@autocommit; --1 代表自动提交 0 代表手动提交

  • 修改默认提交方式:set @@autocommit = 0;

二、事务的四大特征

  • 原子性(atomicity) :事务必须是原子工作单元;对其数据修改,要么全都执行,要么全都不执行【最小的工作单位】

  • 一致性(consistency:事务在完成时,必须使所有的数据都保持一致状态【同时成功或者同时失败】

  • 隔离性(isolation):由并发事务所作的修改必须与任何其他并发事务所作的修改隔离【事务与事务之间相互不影响】

  • 持久性(durability):事务完成之后,它对于系统的影响是永久性的【事务一旦提交不可回滚】

三、事务的隔离级别

1、概念

多个事务之间隔离,相互独立的,但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题:

2、存在的问题

  • ① 脏读:一个事务读取到另一个书屋中没有提交的数据

  • ② 不可重复读(虚读):在同一个事务中,两次读取到的数据不一样

  • ③ 幻读:一个事务操作(DML)数据库中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。

3、隔离级别

隔离的级别:

  • ① read uncommitted: 读未提交
    • 产生的问题:脏读,不可重复读,幻读
  • ② read committed: 读已提交
    • 产生的问题:不可重复读、幻读
  • ③ repeatable read:可重复读
    • 产生的问题:幻读
  • ④ serializable:串行化
    • 可以解决所有的问题

注意:隔离级别从小到大安全性越来越高,但是效率越来越低

隔离级别的设置

  • 数据库查询隔离级别:select @@tx_isolation;

  • 数据库设置隔离级别:`set global transaction isolation level 级别字符串;

注:设置完隔离级别后需要重新打开mysql数据库才会生效。

演示

set global transaction isolation level read uncommitted;
start transaction;
-- 转账操作
update account set balance = balance - 500 where id = 1;
update account set balance = balance + 500 where id = 2;

四、Jdbc事务控制

1、概述

  • 默认事务提交策略:一条命令自成一个完整事务
  • 需求:各个逻辑单元要么一起成功,要么一起失败(比如转账)

2、控制事务的API:

使用Connection对象来管理事务

  • conn.setAutoCommit(false); 将jdbc的事务计较改为手动提交
  • conn.commit(); 手动提交
  • conn.rollback(); 如果事务出错,就让他它回滚

注意:连接提交策略一经设置,永久改变。

3、核心代码

将JDBC自动提交关闭,改成手动提交,然后在让出错的事务在异常里捕获成回滚。这样保证了提交事务出错数据不改动。从而达到数据的正确性。

步骤:

 1. 获取连接Connection对象
 2.Connection对象开启事务
 3.Connection对象获取执行sql语句的Statement对象
 4.定义2条sql语句(2条update语句:扣款,收款)
 5.Statement对象执行sql语句,获取结果
 6.如果sql语句正常执行,没有出现问题,提交事务
 7.处理结果
 8.如果sql语句执行过程中出现问题,回滚事务
 9.关闭资源

代码:

public class Jdbc_affairDemo8 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;

        //1. 获取连接
        try {
            conn = JDBCUtils.getConnection();
            // 建立连接后开启事务
            conn.setAutoCommit(false);

            //2. 定义sql
            //2.1 张三 - 500
            String sql1 = "update account set balance = balance - ? where id = ?";
            //2.2 李四 + 500
            String sql2 = "update account set balance = balance + ? where id = ?";

            //3. 获取执行的sql对象
            pstmt1 = conn.prepareStatement(sql1);
            pstmt2 = conn.prepareStatement(sql2);

            //4. 设置参数
            pstmt1.setDouble(1, 500);
            pstmt1.setInt(2, 1);

            pstmt2.setDouble(1, 500);
            pstmt2.setInt(2, 2);

            //5. 执行sql
            pstmt1.executeUpdate();
            // 手动制造异常
            int i = 3 / 0;
            pstmt2.executeUpdate();

            // 提交事务
            conn.commit();

        } catch (SQLException e) {
            // 事务回滚
            if (conn != null) {
                try {
                    conn.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
            e.printStackTrace();
        } finally {
            JDBCUtils.close(pstmt1, conn);
            JDBCUtils.close(pstmt2, null);
        }
    }
}
发布了22 篇原创文章 · 获赞 14 · 访问量 1158

猜你喜欢

转载自blog.csdn.net/weixin_44157233/article/details/104331947
今日推荐