美文网首页
MySQL 入门(六)

MySQL 入门(六)

作者: yjtuuige | 来源:发表于2022-02-19 07:53 被阅读0次
    7. 使用 IDEA 连接数据库
    • 选择数据源
    image
    • 连接数据库
    image
    • 选择数据库
    image
    • 查看:双击数据表
    image
    • 更新数据:绿色键头提交或快捷键 Ctrl+Enter
    image
    • SQL 语句
    image
    • 如连接失败,查看原因
    image
    8. 事务
    • 概念:事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功

    ACID 原则:

    • 原子性(Atomic);
    • 一致性(Consist);
    • 隔离性(Isolated);
    • 持久性(Durable)。

    隔离性问题

    • 脏读:指一个事务,读取了另外一个事务未提交的数据;
    • 不可重复读:指在一个事务内,读取表中的某一行数据,多次读取结果不同;
    • 虚读(幻读):指在一个事务内,读取到了别的事务插入的数据,导致前后读取不一致。

    代码测试

    -- 创建账户表
    CREATE TABLE `account`(
        `id` INT PRIMARY KEY AUTO_INCREMENT,
        `name` VARCHAR(40),
        `money` FLOAT
    );
    
    -- 插入测试数据
    insert into `account`(`name`,`money`) values('A',1000);
    insert into `account`(`name`,`money`) values('B',1000);
    insert into `account`(`name`,`money`) values('C',1000);
    
    • 当 JDBC 程序向数据库,获得一个 Connection 对象时,默认情况下,这个Connection 对象,会 自动向数据库提交 在它上面发送的 SQL 语句;

    • 若要关闭这种默认提交方式,让多条 SQL 在一个事务中执行,可使用下列的 JDBC 控制事务语句;

      • 开启事务:Connection.setAutoCommit(false);
        • 事务自动关闭;
      • 回滚事务:Connection.rollback();
        • 默认自动回滚;
      • 提交事务:Connection.commit();
    • 测试 1:模拟转账成功时的业务场景

    package com.xxx.demo04;
    
    import com.xxx.demo02.utils.JdbcUtils;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    
    // 模拟转账
    public class TestTransaction01 {
        public static void main(String[] args) {
            Connection conn = null;
            PreparedStatement st = null;
            try {
                conn = JdbcUtils.getConnection();
                // 通知数据库开启事务(start transaction)
                conn.setAutoCommit(false);
    
                String sql1 = "update `account` set `money` = `money`-100 where `name`='A';";
                String sql2 = "update `account` set `money` = `money`+100 where `name`='B';";
                // 执行sql1
                st = conn.prepareStatement(sql1);
                st.executeUpdate();
                // 执行sql2
                st = conn.prepareStatement(sql2);
                st.executeUpdate();
    
                // SQL都执行完毕,通知数据库提交事务(commit)
                conn.commit();
                System.out.println("操作成功!");
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                JdbcUtils.release(conn, st, null);
            }
        }
    }
    
    • 测试 2:模拟程序异常,导致一部分 SQL 执行失败(自动回滚事务)
    package com.xxx.demo04;
    
    import com.xxx.demo02.utils.JdbcUtils;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    
    // 模拟转账
    public class TestTransaction02 {
        public static void main(String[] args) {
            Connection conn = null;
            PreparedStatement st = null;
            try {
                conn = JdbcUtils.getConnection();
                // 通知数据库开启事务(start transaction)
                conn.setAutoCommit(false);
    
                String sql1 = "update `account` set `money` = `money`-100 where `name`='A';";
                String sql2 = "update `account` set `money` = `money`+100 where `name`='B';";
                // 执行sql1
                st = conn.prepareStatement(sql1);
                st.executeUpdate();
    
                // 模拟执行完sql1后,程序出现异常,事务无法正常提交,数据库会自动执行回滚操作
                int x = 1 / 0;
    
                // 执行sql2
                st = conn.prepareStatement(sql2);
                st.executeUpdate();
    
                // SQL都执行完毕,通知数据库提交事务(commit)
                conn.commit();
                System.out.println("操作成功!");
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                JdbcUtils.release(conn, st, null);
            }
        }
    }
    
    • 测试 3:模拟程序异常,导致一部分 SQL 执行失败(手动通知回滚事务)
    package com.xxx.demo04;
    
    import com.xxx.demo02.utils.JdbcUtils;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    
    // 模拟转账
    public class TestTransaction03 {
        public static void main(String[] args) {
            Connection conn = null;
            PreparedStatement st = null;
            try {
                conn = JdbcUtils.getConnection();
                // 通知数据库开启事务(start transaction)
                conn.setAutoCommit(false);
    
                String sql1 = "update `account` set `money` = `money`-100 where `name`='A';";
                String sql2 = "update `account` set `money` = `money`+100 where `name`='B';";
                // 执行sql1
                st = conn.prepareStatement(sql1);
                st.executeUpdate();
    
                // 模拟执行完sql1后,程序出现异常,事务无法正常提交
                int x = 1 / 0;
    
                // 执行sql2
                st = conn.prepareStatement(sql2);
                st.executeUpdate();
    
                // SQL都执行完毕,通知数据库提交事务(commit)
                conn.commit();
                System.out.println("操作成功!");
            } catch (SQLException e) {
                // 捕获到异常,手动通知数据库,执行回滚事务的操作
                try {
                    conn.rollback();
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
                e.printStackTrace();
            } finally {
                JdbcUtils.release(conn, st, null);
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:MySQL 入门(六)

          本文链接:https://www.haomeiwen.com/subject/vwuslrtx.html