JDBC——JDBC中的事务、DBUtils使用事务

目录


什么是事务?

跳转到目录
事务概述

  • 事务指的是逻辑上的一组操作,组成这组操作的各个单元要么全都成功,要么全都失败.
  • 事务作用:保证在一个事务中多次SQL操作要么全都成功,要么全都失败.

JDBC中的事务

跳转到目录

  • JDBC完成转账功能(加入事务管理)
    场景: tom 欠 jerry 1000元 使用2条update语句
    1. tom-1000
    2. jerry+1000

    • 以上2条sql应该看成一组(一个整体),必须使用一个事务,必须保证使用同一个Connection对象
    • 以上2条sql要么全部都执行,要么全部都不执行

事务管理流程

    1.开启事务
    2.执行sql语句,多条sql语句正常执行,没有出现问题,提交事务,把数据持久化到数据库
    3.执行sql语句,多条sql语句执行过程中出现问题,回滚事务,把数据回退到开启事务之前的状态
    4.关闭资源

JDBC事务操作

与事务相关的方法,都定义在java.sql.Connection接口中:

  • public void setAutoCommit(boolean flag): 将此连接的自动提交模式设置为给定状态flag。
    参数:
    boolean flag:
    - 为 true 表示启用自动提交模式
    - 为 false 表示禁用自动提交模式,手动提交,开启事务

  • public void commit(): 提交事务,把数据持久化到数据库

  • void rollback(): 取消在当前事务中进行的所有更改,回滚事务,把数据回退到开启事务之前的状态

步骤:

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

伪代码:

try{
      1.获取连接Connection对象
       2.开启事务
       con.setAutoCommit()
       3.Connection对象获取执行sql语句的Statement对象
       4.定义2条sql语句(2条update语句:扣款,收款)
       5.Statement对象执行sql语句,获取结果
       6.如果sql语句正常执行,没有出现问题,提交事务
       con.commit;
       7.处理结果
   	} catch(Exception e){
       8.如果sql语句执行过程中出现问题,回滚事务
       con.rollback;
   } finally{
       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);
        }
    }
}

DBUtils使用事务

跳转到目录
使用DBUtils工具类: 目的简化JDBC的开发步骤,不关心Connection连接对象如何获取,不关心事务管理的事情

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

QueryRunner核心类

  • public QueryRunner(): 可以直接创建对象,但是没有传递Connection连接对象
    所以该对象调用方法,执行增删改查时,必须传Connection连接对象

  • public QueryRunner(DataSource ds) : 创建对象,必须传递连接池对象,创建QueryRunner对象时,传递连接池对象,执行增删改查的方法时,QueryRunner对象会从连接池获取连接对象,但是获取的是哪个连接对象,我们不知道,我们也看不见,所以我们不能完成事务管理的工作

步骤:

    1.空参构造创建QueryRunner对象
    2.获取连接对象
    3.连接对象开启事务
    4.QueryRunner对象执行sql语句获取结果
    5.sql语句正常执行,提交事务,处理结果
    6.sql语句出现问题,回滚事务
    7.关闭资源

DBUtils中的工具类DbUtils,静态方法:

  • public static void commitAndCloseQuietly(Connection conn): 提交事务,关闭连接,内部进行try-catch异常处理
  • public static void rollbackAndCloseQuietly(Connection conn): 回滚事务,关闭连接,内部进行try-catch异常处理
public class Demo04Account {
    public static void main(String[] args) {
        Connection con = null;
        try {
            //1.空参构造创建QueryRunner对象
            QueryRunner qr = new QueryRunner();

            //2.获取连接对象
            con = C3P0Util.getConnection();

            //3.连接对象开启事务
            con.setAutoCommit(false);

            //定义2条sql语句(2条update语句:扣款,收款)
            String tomSql = "update account set money=money-? where name=?";
            String jerrySql = "update account set money=money+? where name=?";

            //4.QueryRunner对象执行sql语句获取结果
            int tomResult = qr.update(con, tomSql, 1000, "tom");

            System.out.println(1/0);//出异常了

            int jerryResult = qr.update(con, jerrySql, 1000, "jerry");

            //5.sql语句正常执行,提交事务,处理结果
            DbUtils.commitAndCloseQuietly(con);//提交事务,关闭连接,内部进行try-catch异常处理

            if(tomResult>0) {
                System.out.println("tom账户成功扣款1000元~~~");
            } else {
                System.out.println("tom账户扣款1000元失败~~~");
            }

            if(jerryResult>0) {
                System.out.println("jerry账户收款1000元成功~~~");
            } else {
                System.out.println("jerry账户收款1000元失败~~~");
            }


        } catch (Exception e) {
            e.printStackTrace();
            //6.sql语句出现问题,回滚事务
            DbUtils.rollbackAndCloseQuietly(con);//回滚事务,关闭连接,内部进行try-catch异常处理
        }
    }

发布了150 篇原创文章 · 获赞 68 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/m0_37989980/article/details/104079330