JDBC事务操作

1、 事务概述

事务的概念:逻辑上的一组SQL语句(一个或者多个)执行的时候要么全部执行成功,要么全部执行失败。

事务的案例:转账案例:一个账户中的余额减少,另一个账户中的余额增加。

更新数据:update set 余额=原有的余数 - 要转账的余额 where 转出账户的账户

更新语句:update set 余额=原有的余额+ 要转账的余额 where 转入账户的账户

要执行的SQL语句是两个update语句,要么都成功,要么都失败,不允许一个执行成功,另一个执行失败。

同一组SQL语句,就是用同一个数据库连接对象执行的!

  • 数据准备

-- 1:创建一个银行数据库
create database if not exists  bank;
​
-- 2: 打开数据库
use bank;
​
​
-- 3: 创建银行账户
create table if not exists  account(
    id int primary key auto_increment,
    name varchar(20),
    money double
);
​
-- 4:插入tom和jerry的账户表1000
insert into account(name, money) VALUES ('tom',2000),('jerry',2000);
​
​
-- 5:查询数据表
select * from account;
​
-- 6:修改数据表
update account set money=2000;

2、 事务的具体操作

  • 开启事务,或者称为阻止事务的自动提交

  • 提交事务,所有SQL语句都执行成功,提交事务,数据持久化

  • 回滚事务,如果有部分SQL语句执行失败,回滚事务,数据不会改变

数据库自身事务的操作命令:

命令命令的作用
begin开启事务
commit提交事务
rollback回滚事务

Java中的事务操作:核心是数据库连接对象Connection:

数据库连接对象的方法方法的作用
setAutoCommit(false)开启事务,阻止事务的自动提交
commit提交事务
rollback回滚事务

每个数据库连接对象都有自己的事务,针对当前的数据库连接对象是有效的!

一旦事务提交或者回滚,当前事务就结束了!

7.3 原始JDBC转账案例中的事务

需求:JDBC技术实现转账功能,tom账户向jerry账户转1000元。

①:添加Lib库中的jar包

②:druid.properties配置文件

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/school
username=root
password=mysql密码
initialSize=10
maxActive=20

③:创建units包指的是DataSourceUtils

package com.rocky.utils;
​
import com.alibaba.druid.pool.DruidDataSourceFactory;
​
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
​
public class DataSourceUtils {
    static DataSource dataSource;
    static{
        InputStream resourceAsStream =
                DataSourceUtils.class.getClassLoader().getResourceAsStream("druid.properties");
​
        Properties properties=new Properties();
​
        try {
            properties.load(resourceAsStream);
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
​
    public static DataSource getDataSource(){
        return dataSource;
    }
​
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
​
    public static void close(ResultSet resultSet, Statement statement,Connection connection) throws SQLException {
​
        if(resultSet!=null){
            resultSet.close();
        }
​
        if(statement!=null){
            statement.close();
        }
​
        if(connection!=null){
            connection.close();
        }
​
    }
}
 

④:准备pojo中的javaBean

package com.rocky.pojo;
​
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
​
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account {
    
    private Integer id;
    private String name;
    private double money;
}
​

⑤:不使用事务操作

创建一个NoTransfer的事务类

package com.rocky.transfer;
import com.rocky.utils.DataSourceUtils;
​
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
​
/**
 * 实现转账功能
 * 功能的实现步骤
 * 1:定义需要的数据,收款人和付款人的姓名,转账金额
 * 2: 定义2个更新语句 update语句
 * 3:使用同一个数据库连接对象执行SQL语句
 * */
public class NoTransfer {
​
    public static void main(String[] args) throws SQLException {
        // 付款人的姓名tom
        String fromName="tom";
        // 收款人的姓名jerry
        String toName="jerry";
        //转账金额
        double money=500;
        //定义数据库操作需要的对象
        Connection connection=null;
        PreparedStatement preparedStatement=null;
​
        try {
            //从连接池中获取数据库连接
            connection= DataSourceUtils.getConnection();
​
            //获取SQL语句的执行对象
            // 减钱的SQL语句
            String sql1="update account set money=money-? where name=?";
            preparedStatement=connection.prepareStatement(sql1);
​
            preparedStatement.setObject(1,money);
            preparedStatement.setObject(2,fromName);
            //执行SQL语句
            int num1 = preparedStatement.executeUpdate();
​
​
​
//            // 增加钱的SQL语句
            String sql2="update account set money=money+? where name=?";
​
            preparedStatement=connection.prepareStatement(sql2);
​
            preparedStatement.setObject(1,money);
            preparedStatement.setObject(2,toName);
            //执行SQL语句
            int num2=preparedStatement.executeUpdate();
​
            //打印出结果
            System.out.println("num1="+num1+"num2="+num2);
​
​
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            DataSourceUtils.close(null,preparedStatement,connection);
        }
​
    }
}
​

执行成功:

中间人为的加一个错误

   //中间加一句话 模拟出现一个错误
            double a=1/0;
package com.rocky.transfer;
import com.rocky.utils.DataSourceUtils;
​
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
​
/**
 * 实现转账功能
 * 功能的实现步骤
 * 1:定义需要的数据,收款人和付款人的姓名,转账金额
 * 2: 定义2个更新语句 update语句
 * 3:使用同一个数据库连接对象执行SQL语句
 * */
public class NoTransfer {
​
    public static void main(String[] args) throws SQLException {
        // 付款人的姓名tom
        String fromName="tom";
        // 收款人的姓名jerry
        String toName="jerry";
        //转账金额
        double money=500;
        //定义数据库操作需要的对象
        Connection connection=null;
        PreparedStatement preparedStatement=null;
​
        try {
            //从连接池中获取数据库连接
            connection= DataSourceUtils.getConnection();
​
            //获取SQL语句的执行对象
            // 减钱的SQL语句
            String sql1="update account set money=money-? where name=?";
            preparedStatement=connection.prepareStatement(sql1);
​
            preparedStatement.setObject(1,money);
            preparedStatement.setObject(2,fromName);
            //执行SQL语句
            int num1 = preparedStatement.executeUpdate();
​
​
            //中间加一句话
            double a=1/0;
​
//            // 增加钱的SQL语句
            String sql2="update account set money=money+? where name=?";
​
            preparedStatement=connection.prepareStatement(sql2);
​
            preparedStatement.setObject(1,money);
            preparedStatement.setObject(2,toName);
            //执行SQL语句
            int num2=preparedStatement.executeUpdate();
​
            //打印出结果
            System.out.println("num1="+num1+"num2="+num2);
​
​
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            DataSourceUtils.close(null,preparedStatement,connection);
        }
​
    }
}
​

这就是没有事务操作的写法

⑥:使用事务的操作

package com.rocky.transfer;
import com.rocky.utils.DataSourceUtils;
​
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
​
/**
 * 实现转账功能
 * 功能的实现步骤
 * 1:定义需要的数据,收款人和付款人的姓名,转账金额
 * 2: 定义2个更新语句 update语句
 * 3:使用同一个数据库连接对象执行SQL语句
 * */
public class NoTransfer {
​
    public static void main(String[] args) throws SQLException {
        // 付款人的姓名tom
        String fromName="tom";
        // 收款人的姓名jerry
        String toName="jerry";
        //转账金额
        double money=500;
        //定义数据库操作需要的对象
        Connection connection=null;
        PreparedStatement preparedStatement=null;
​
        try {
            //从连接池中获取数据库连接
            connection= DataSourceUtils.getConnection();
​
            // 关闭事务的自动提交
            connection.setAutoCommit(false);
​
            //获取SQL语句的执行对象
            // 减钱的SQL语句
            String sql1="update account set money=money-? where name=?";
            preparedStatement=connection.prepareStatement(sql1);
​
            preparedStatement.setObject(1,money);
            preparedStatement.setObject(2,fromName);
            //执行SQL语句
            int num1 = preparedStatement.executeUpdate();
​
​
            //中间加一句话
            double a=1/0;
​
//            // 增加钱的SQL语句
            String sql2="update account set money=money+? where name=?";
​
            preparedStatement=connection.prepareStatement(sql2);
​
            preparedStatement.setObject(1,money);
            preparedStatement.setObject(2,toName);
            //执行SQL语句
            int num2=preparedStatement.executeUpdate();
​
            //打印出结果
            System.out.println("num1="+num1+"num2="+num2);
​
            //SQL语句执行完毕,没有发生异常,说明执行成功了,提交事务处理
            connection.commit();
​
​
        }catch (Exception e){
            e.printStackTrace();
            //如果出现异常,要回滚事务,注意 要用Exception去抓取,SQLException抓不到
            connection.rollback();
        }finally {
            DataSourceUtils.close(null,preparedStatement,connection);
        }
​
    }
}
 

执行成功:

package com.rocky.transfer;
import com.rocky.utils.DataSourceUtils;
​
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
​
/**
 * 实现转账功能
 * 功能的实现步骤
 * 1:定义需要的数据,收款人和付款人的姓名,转账金额
 * 2: 定义2个更新语句 update语句
 * 3:使用同一个数据库连接对象执行SQL语句
 * */
public class NoTransfer {
​
    public static void main(String[] args) throws SQLException {
        // 付款人的姓名tom
        String fromName="tom";
        // 收款人的姓名jerry
        String toName="jerry";
        //转账金额
        double money=500;
        //定义数据库操作需要的对象
        Connection connection=null;
        PreparedStatement preparedStatement=null;
​
        try {
            //从连接池中获取数据库连接
            connection= DataSourceUtils.getConnection();
​
            // 关闭事务的自动提交
            connection.setAutoCommit(false);
​
            //获取SQL语句的执行对象
            // 减钱的SQL语句
            String sql1="update account set money=money-? where name=?";
            preparedStatement=connection.prepareStatement(sql1);
​
            preparedStatement.setObject(1,money);
            preparedStatement.setObject(2,fromName);
            //执行SQL语句
            int num1 = preparedStatement.executeUpdate();
​
​
            //中间加一句话
//            double a=1/0;
​
//            // 增加钱的SQL语句
            String sql2="update account set money=money+? where name=?";
​
            preparedStatement=connection.prepareStatement(sql2);
​
            preparedStatement.setObject(1,money);
            preparedStatement.setObject(2,toName);
            //执行SQL语句
            int num2=preparedStatement.executeUpdate();
​
            //打印出结果
            System.out.println("num1="+num1+"num2="+num2);
​
            //SQL语句执行完毕,没有发生异常,说明执行成功了,提交事务处理
            connection.commit();
​
​
        }catch (Exception e){
            e.printStackTrace();
            //如果出现异常,要回滚事务,注意 要用Exception去抓取,SQLException抓不到
            connection.rollback();
        }finally {
            DataSourceUtils.close(null,preparedStatement,connection);
        }
​
    }
}
 

一次要执行多条SQL语句(增删改)的时候,会出现数据错误问题,因此必须要添加事务!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值