数据库事务超全干货

​​​​​​小伙伴们,在说干货之前,为了更通俗易懂,先来点小菜,岂不是更美滋滋吗~~~嚯嚯

 

业务讲解:转账案例(小菜)

 

①小明付钱:  update account set money=money-1000 where name=’xiaoming’;

②小红收钱:  update account set money=money+1000 where name=’xiaohong’;

 

 

流程图:

 

 

代码实现:

AccountTest:

public class AccountTest {
    private AccountService service = new AccountService();
    @Test
    public void run1(){
        //1、准备数据
        String userIn = "xiaohong";//收款人
        String userOut = "xiaoming";//付款人
        double money = 1000.0;//转账金额
        //2、调用service开始转账
        boolean flag = service.account(userIn,userOut,money);
        //3、根据service的结果,判断转账成功/失败
        if(flag){
            System.out.println("转账成功");
        }else{
            System.out.println("转账失败");
        }
    }
}

 

AccountService

public class AccountService {
    private AccountDao dao = new AccountDao();
    /**
     * 转账功能
     * @param userIn
     * @param userOut
     * @param money
     * @return
     */
    public boolean account(String userIn, String userOut, double money) {
        try {
            //1、付款人 付款
            dao.userOut(userOut,money);
            //2、收款人 收款
            dao.userIn(userIn,money);
        } catch (Exception e) {
            //出了异常,转账失败
            return false;
        }
        //没出异常,转账成功
        return true;
    }
}

 

AccountDao

/**
 * 付款人 付款
 * @param userOut
 * @param money
 */
public void userOut(String userOut, double money) throws SQLException {
    //1、获取连接
    Connection con = JDBCUtils.getConnection();
    //2、获取发送SQL语句对象
    PreparedStatement ps = con.prepareStatement("update account set money=money-? where name=?");
    ps.setDouble(1,money);
    ps.setString(2,userOut);
    //3、发送SQL语句
    ps.executeUpdate();
    //4、关闭资源
    JDBCUtils.closeAll(con,ps,null);
}

/**
 * 收款人 收款
 * @param userIn
 * @param money
 */
public void userIn(String userIn, double money) throws SQLException {
    //1、获取连接
    Connection con = JDBCUtils.getConnection();
    //2、获取发送SQL语句对象
    PreparedStatement ps = con.prepareStatement("update account set money=money+? where name=?");
    ps.setDouble(1,money);
    ps.setString(2,userIn);
    //3、发送SQL语句
    ps.executeUpdate();
    //4、关闭资源
    JDBCUtils.closeAll(con,ps,null);
}

 

  • 如果付款成功,收款失败,转账失败,会导致付款的钱无法还原而丢失。

解决:

转账失败,所有的操作还原。

转换成功,所有的操作永久保存数据库。

 

 

 

一.数据库事务

1.简述

概念:事务指的是逻辑上的一组操作,组成这组操作的各个单元要么全都成功,要么全都失败.

  • 事务:数据的回收站
  • 作用:保证数据完整,保证数据的安全

 

2.MySQL事务操作

MySQL有两种事务操作,

  • 手动事务
  • 自动事务(默认开启)

 

手动事务:

  • 手动事务:先手动开启事务,再手动提交 或者手动回滚事务。

sql语句

描述

start transaction;

开启事务

 

开启了一次数据回收站功能。

 

在当前事务中进行的任何数据的增删改都可以被永久保存/还原。

commit;

提交事务

 

把当前事务中操作过的数据,永久保存。

关闭当前的手动事务

rollback;

回滚事务

 

还原事务中操作过的数据。

关闭当前的手动事务

 

 

 

例如:

 

 

手动事务的注意事项:

1、commit或rollback之后,若需要再次使用事务,必须再次开启事务。

2、事务仅针对DML(增删改)和DQL(查)语句

   若遇到其他语句(例如:DDL语句),事务会强制提交并关闭

 

 

 

  • 自动事务:执行任何DML语句时,MySQL自动开启事务,并自动提交事务

自动事务无法回滚只能提交

 

优点:提升程序员代码测试效率

缺陷:一句一个事务,效率不高,无法自定义事务

 

自动事务关闭:

临时关闭:

手动开启事务:start transcation;

本次永久关闭:

set autocommit = 0;    #0:OFF  1:ON

 

 

 

3.JDBC事务操作

JDBC事务的两大前提:

1、因为转账业务相当于转账事务,所以事务控制代码需要加在service业务层

2、一个事务中的所有的SQL语句,必须使用同一个Connection对象,这样才能保证正常的事务控制

 

   Connection

方法名

描述

setAutoCommit(boolean flag)

设置事务是否为自动事务。

参数:true(默认)自动事务

      false 手动事务,开启一次手动事务

 

setAutoCommit(false);

会通知JDBC发送start transaction;给MySQL执行

 

commit();

提交事务

 

会通知JDBC发送commit;给MySQL执行

rollback();

回滚事务

 

会通知JDBC发送rollback;给MySQL执行

 

 

修改代码:

AccountService:

public boolean account(String userIn, String userOut, double money) {
    Connection con = null;
    try {
        //因为事务是在service层,一个事务下的所有操作应该在一个Connection对象中
        con = JDBCUtils.getConnection();
        //设置手动事务
        con.setAutoCommit(false);
        //1、付款人 付款
        dao.userOut(con, userOut, money);
        int a = 1 / 0;
        //2、收款人 收款
        dao.userIn(con, userIn, money);
        //没出异常,提交
        con.commit();
    } catch (Exception e) {
        //出了异常,转账失败
        try {
            if(con!=null)
                con.rollback();
        } catch (SQLException e1) {
        }
        return false;
    } finally {
        //无论如何都要关闭连接
        try {
            JDBCUtils.closeAll(con,null,null);
        } catch (SQLException e) {
        }
    }
    //没出异常,转账成功
    return true;
}

 

 

 

AccountDao:

/**
     * 付款人 付款
     * @param con
     * @param userOut
     * @param money
     */
    public void userOut(Connection con, String userOut, double money) throws SQLException {
        //1、获取连接
//        Connection con = JDBCUtils.getConnection();
        //2、获取发送SQL语句对象
        PreparedStatement ps = con.prepareStatement("update account set money=money-? where name=?");
        ps.setDouble(1,money);
        ps.setString(2,userOut);
        //3、发送SQL语句
        ps.executeUpdate();
        //4、关闭资源
        JDBCUtils.closeAll(null,ps,null);
    }

    /**
     * 收款人 收款
     * @param con
     * @param userIn
     * @param money
     */
    public void userIn(Connection con, String userIn, double money) throws SQLException {
        //1、获取连接
//        Connection con = JDBCUtils.getConnection();
        //2、获取发送SQL语句对象
        PreparedStatement ps = con.prepareStatement("update account set money=money+? where name=?");
        ps.setDouble(1,money);
        ps.setString(2,userIn);
        //3、发送SQL语句
        ps.executeUpdate();
        //4、关闭资源
        JDBCUtils.closeAll(null,ps,null);
    }

 

 

 

 

小结:

事务代码加在service层

同一个事务下所有的sql语句,用的是同一个Connection对象

 

 

 

 

 

 

看完恭喜你,又知道了一点点!!!

你知道的越多,不知道的越多! 

~感谢志同道合的你阅读,  你的支持是我学习的最大动力 ! 加油 ,陌生人一起努力,共勉!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值