MySQL事务(transaction)之手动控制sql事务及JDBC事务的开启

1.概念

事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。

2.管理事务

2.1数据库默认的事务

数据库默认支持事务,默认的事务是:一条sql一个事务。

2.2手动控制事务

sql控制事务

开启事务:start transaction;

开启事务后,在这条语句之后的所有sql都将处在同一个事务中

提交事务:commit;

从开启事务到提交事务之间的所有sql一起执行

回滚事务:rollback;

从开启事务到回滚事务之间的所有sql一起失效

sql脚本示例如下:

说明:当开启事务START TRANSACTION;后执行给a用户扣款100,给b用户加钱100,如果commit,那么a被扣除100,b则增加100。如果执行rollback,那么a和b的金额就会保持不变。

#slq控制事务,
#开启事务
START TRANSACTION;
UPDATE myuser SET money= money-100 WHERE name='a';
UPDATE myuser SET money= money+100 WHERE name='b';
COMMIT;
#回滚会取消开启到结束的所有sql
ROLLBACK;
#查看修改后的数据,验证事务
SELECT* FROM myuser;

JDBC控制事务

开启事务:conn.setAutoCommit(false);

jdbc中sql会自动提交,如果设置sql不自动提交,就需要我们手动提交,即提交前的所有sql在一个事务中

提交事务:conn.commit();

回滚事务:conn.rollback();

示例代码如下:

说明:测试类TransactionDemo1用于测试JDBC的事务控制,其中会用到JdbcUtils工具类(代码可参见:https://blog.csdn.net/qq_32224047/article/details/106722020

情况一:不开启事务,在sql1和sql2中间加入异常int i = 1/0;

package cn.wy.jdbc.transaction;

import cn.wy.jdbc.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * JDBC 事务测试类
 * @author wyy
 * @date 2020/6/23 10:33
 */
public class TransactionDemo1 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql1 = "UPDATE myuser SET money= money-100 WHERE name=?";
            ps = conn.prepareStatement(sql1);
            ps.setString(1,"a");
            ps.executeUpdate();
            //加入错误,验证事务不开启,jdbc自动提交(a被扣钱,b没有加钱,因为默认提交,上面的sql1执行,slq2 为执行)
            int i = 1/0;

            String sql2 = "UPDATE myuser SET money= money+100 WHERE name=?";
            ps = conn.prepareStatement(sql2);
            ps.setString(1,"b");
            ps.executeUpdate();     

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JdbcUtils.close(rs,conn,ps);
        }
    }
}

代码执行前a和b用户金额都是1000

执行上面代码抛出异常

查询数据库a用户被扣除100元,但是b用户并没有增加100元,因为jdbc默认是开启了事务管理,当执行完成sql1后,出现异常,无法在执行到sql2,所有sql1执行后被提交,之后的数据就不在执行,就出现了下面的查询结果。

注意:在执行事务相关的操作时需要先检查一下当前数据库的隔离级别,MySQL默认隔离级别:repeatable read。可以用select @@tx_isolation;查询当前的隔离级别。当前的测试都是在默认的隔离级别下执行。如果是其他的隔离级别可能无法得到该测试想要的结果。

隔离级别的检查如下:

情况二:开启事务,在sql1和sql2中间加入异常int i = 1/0;

package cn.wy.jdbc.transaction;

import cn.wy.jdbc.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * JDBC 事务测试类
 * @author wyy
 * @date 2020/6/23 10:33
 */
public class TransactionDemo1 {
    public static void main(String[] args) {
            //开启事务
            conn.setAutoCommit(false);
            conn = JdbcUtils.getConnection();
            String sql1 = "UPDATE myuser SET money= money-100 WHERE name=?";
            ps = conn.prepareStatement(sql1);
            ps.setString(1,"a");
            ps.executeUpdate();
            //加入错误,验证事务(a被扣钱,b没有加钱,因为默认提交,上面的sql1执行,slq2 为执行)
            int i = 1/0;

            String sql2 = "UPDATE myuser SET money= money+100 WHERE name=?";
            ps = conn.prepareStatement(sql2);
            ps.setString(1,"b");
            ps.executeUpdate();

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

        }catch (Exception e){
            e.printStackTrace();
            //如果出现任何异常则,执行回滚
            if (conn!=null){
                try {
                    conn.rollback();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }finally {
            JdbcUtils.close(rs,conn,ps);
        }
    }
}

执行代码前先将a和b用户的账户金额都还原为1000

执行程序,抛出NullPointerException异常

查询数据库,结果并未改变,由于开启了事务,当出现异常时,后在catch中捕获后执行回滚(rollback),从而保证一个事务要么全部成功,要么全部不成功。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JDBCJava Database Connectivity)是Java语言访问数据库的一种标准规范,它提供了一套用于操作关系型数据库的API,包括连接数据库、执行SQL语句、处理结果集等。 事务是指一组操作,它们被视为一个整体,要么全部执行成功,要么全部失败回滚。在JDBC,可以使用Transaction来管理事务JDBC事务处理包括以下几个步骤: 1. 获取数据库连接对象Connection。 2. 关闭自动提交,设置事务的隔离级别和超时时间。 3. 开始事务,使用Connection对象的beginTransaction()方法。 4. 执行SQL语句,使用Statement或PreparedStatement对象。 5. 如果执行过程发生异常,使用Connection对象的rollback()方法回滚事务,否则使用commit()方法提交事务。 6. 关闭Statement或PreparedStatement对象。 7. 关闭Connection对象。 下面是一个简单的示例代码: ```java import java.sql.*; public class JdbcTransactionExample { public static void main(String[] args) { Connection conn = null; PreparedStatement pstmt = null; try { // 获取数据库连接 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456"); // 关闭自动提交 conn.setAutoCommit(false); // 设置事务的隔离级别和超时时间 conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); conn.setTransactionTimeout(10); // 开始事务 conn.beginTransaction(); // 执行SQL语句 pstmt = conn.prepareStatement("UPDATE users SET balance=balance-100 WHERE id=?"); pstmt.setInt(1, 1); pstmt.executeUpdate(); pstmt = conn.prepareStatement("UPDATE users SET balance=balance+100 WHERE id=?"); pstmt.setInt(1, 2); pstmt.executeUpdate(); // 提交事务 conn.commit(); } catch (SQLException e) { // 回滚事务 try { if (conn != null) { conn.rollback(); } } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); } finally { // 关闭PreparedStatement和Connection对象 try { if (pstmt != null) { pstmt.close(); } if (conn != null) { conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } } } ``` 在上面的示例,我们使用了PreparedStatement对象来执行SQL语句,并使用Connection对象的beginTransaction()、commit()和rollback()方法来管理事务。注意,如果在执行SQL语句的过程发生异常,需要使用conn.rollback()方法回滚事务。最后,需要关闭PreparedStatement和Connection对象。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值