数据库事务超全干货

广告位

1 ​​​​​​小伙伴们,在说干货之前,为了更通俗易懂,先来点小菜,岂不是更美滋滋吗~~~嚯嚯 业务讲解:转账…

1

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

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

数据库事务超全干货

①小明付钱:  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对象

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

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

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

女人的秘密

关于作者: 女人的秘密

为您推荐