欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JDBC事务处理

程序员文章站 2022-03-06 18:34:58
...
1. 事务的概念

事务处理在数据库开发中有着非常重要的作用,所谓事务就是所有的操作要么一起成功,要么一起失败,事务本身具有原子性(Atomicity)、一致性(Consistency)、隔离性或独立性(Isolation)、持久性(Durability)4个特性,这4个特性也被称为ACID特征。

原子性:原子性是事务最小的单元,是不可再分隔的单元,相当于一个个小的数据库操作,这些操作必须同时成功,如果一个失败了,则一切的操作将全部失败。

一致性:指的是在数据库操作的前后是完全一致的,保证数据的有效性,如果事务正常操作则系统会维持有效性,如果事务出现了错误,则回到最原始状态,也要维持其有效性,这样保证事务开始时和结束时系统处于一致状态。

隔离性:多个事务可以同时进行且彼此之间无法访问,只有当事务完成最终操作时,才可以看到结果。

持久性:事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。


2. MySQL对事务的支持

序号 命令 描述
1 SET AUTOCOMMIT=0    取消自动提交处理,开启事务处理
2 SET AUTOCOMMIT=1    打开自动提交处理,关闭事务处理
3 START TRANSACTION    启动事务
4 BEGIN    启动事务,相当于执行 START TRANSACTION
5 COMMIT    提交事务
6 ROLLBACK    回滚全部事务
7 SAVEPOINT 事务保存点名称    设置事务保存点
8 ROLLBACK TO SAVEPOINT 保存点名称    回滚操作到保存点


3. JDBC事务处理

4. 事务保存点

create table t_account (
  id int(11) not null auto_increment,
  accountname varchar(20) default null,
  accountbalance int(11) default null,
  primary key (id)
) engine=innodb auto_increment=3 default charset=utf8;

insert into t_account(id,accountName,accountBalance) values (1,'张三',500),(2,'李四',1000);

Demo01.java

package com.andrew.jdbc.chap09;

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

import com.andrew.jdbc.util.DbUtil;

public class Demo01 {
    private static DbUtil dbUtil = new DbUtil();

    // 转出
    private static void outCount(Connection con, String accountName, int account) throws Exception {
        String sql = "update t_account set accountBalance=accountBalance-? where accountName=?";
        PreparedStatement pstmt = con.prepareStatement(sql);
        pstmt.setInt(1, account);
        pstmt.setString(2, accountName);
        pstmt.executeUpdate();
    }

    // 转入
    private static void inCount(Connection con, String accountName, int account) throws Exception {
        String sql = "update t_account set accountBalance=accountBalance+? where accountName=?";
        PreparedStatement pstmt = con.prepareStatement(sql);
        pstmt.setInt(1, account);
        pstmt.setString(2, accountName);
        pstmt.executeUpdate();
    }

    public static void main(String[] args) {
        Connection connection = null;
        try {
            connection = dbUtil.getConnection();
            connection.setAutoCommit(false); // 取消自动提交
            System.out.println("张三开始向李四转账!");
            int account = 500;
            outCount(connection, "张三", account);
            inCount(connection, "李四", account);
            System.out.println("转账成功!");
        } catch (Exception e) {
            try {
                connection.rollback(); // 回滚
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            try {
                connection.commit(); // 提交事务
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

张三开始向李四转账!
转账成功!
500 1000 ->
0 1500
如果修改sql语句报错则不能执行


Demo02.java

package com.andrew.jdbc.chap09;

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

import com.andrew.jdbc.util.DbUtil;

public class Demo02 {
    private static DbUtil dbUtil = new DbUtil();

    // 转出
    private static void outCount(Connection con, String accountName, int account) throws Exception {
        String sql = "update t_account set accountBalance=accountBalance-? where accountName=?";
        PreparedStatement pstmt = con.prepareStatement(sql);
        pstmt.setInt(1, account);
        pstmt.setString(2, accountName);
        pstmt.executeUpdate();
    }

    // 转入
    private static void inCount(Connection con, String accountName, int account) throws Exception {
        String sql = "update t_account set account=accountBalance+? where accountName=?";
        PreparedStatement pstmt = con.prepareStatement(sql);
        pstmt.setInt(1, account);
        pstmt.setString(2, accountName);
        pstmt.executeUpdate();
    }

    public static void main(String[] args) {
        Connection connection = null;
        Savepoint savepoint = null;
        try {
            connection = dbUtil.getConnection();
            connection.setAutoCommit(false); // 取消自动提交
            System.out.println("张三开始向李四转账!");
            int account = 500;
            outCount(connection, "张三", account);
            savepoint = connection.setSavepoint(); // 设置一个保存点
            inCount(connection, "李四", account);
            System.out.println("转账成功!");
        } catch (Exception e) {
            try {
                connection.rollback(savepoint); // 回滚到savepoint保存点
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            try {
                connection.commit(); // 提交事务
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果:
张三开始向李四转账!
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'account' in 'field list'
500 1000 ->
0 1000
相关标签: jdbc