zoukankan      html  css  js  c++  java
  • 事务(Transaction)

    1、演示转账的功能:
    (1)创建一张表示学生表表
    CREATE TABLE student(
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    account DECIMAL(11,2)

    )

    (2)向表中插入几个用户
    INSERT INTO student(id,name,account ) VALUES(NULL,'stu1',1000);
    INSERT INTO student(id,name,account ) VALUES(NULL,'stu2',1000);
    SELECT * FROM student;

    (3)stu1向stu2转账100元
    从stu1的账号减去100元
    UPDATE student SET account = account - 100 WHERE name='stu1';

    #给shaheshang的账号加上100元
    UPDATE student SET account = account +100 WHERE name = 'stu2';

    重新设置为1000元:
    UPDATE student SET account =1000;

    2、用代码演示上述过程

     1 //StudentDao类
     2 public static int updateAge(Connection conn,Integer id,Integer account) {
     3     Connection conn = null;
     4     PreparedStatement ps = null;
     5     String sql = "update student set account=account+? where id=?";
     6     int i = 0;
     7     try {
     8         conn = DBUtil.getConn();
     9         ps = conn.prepareStatement(sql);
    10         ps.setInt(1, account);
    11         ps.setInt(2, id);
    12         i = ps.executeUpdate();
    13     } catch (SQLException e) {
    14         e.printStackTrace();
    15     } finally{
    16         DBUtil.close(conn, ps, null);
    17     }
    18     return i;
    19 }
    20 //测试类
    21 @Test
    22 public void testTransaction() {
    23     try {
    24         StudentDao.updateAccount(conn, 1, -100);
    25         //int i=10/0;
    26         StudentDao.updateAccount(conn, 2, 100);
    27     } catch (SQLException e) {
    28         e.printStackTrace();
    29     }
    30 }

    正常执行,没有问题,但是若将 int i=10/0; 处的注解放开,则id为1的账户减少100元,id为2的账户并没有增加100元,银行赚了。

    3、用事务的方式解决上述问题

    事务(Transaction)

    • 事务的特性(ACID):
      • 原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
      • 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
      • 隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
      • 持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
    • 操作事务的基本步骤:
      • 开启事务:开启事务以后,我们以后的所有操作将都会在同一个事务当中
      • 操作数据库:开启事务以后再去操作数据库,所有操作将不会直接提交到数据库中
      • 提交事务:将修改应用到数据库
      • 回滚事务:数据库操作过程中出现异常了,回滚事务,回滚事务以后,数据库变成开启事务之前的状态
    • mysql中的事务控制
      • 开启事务:START TRANSACTION
      • 提交事务:COMMIT
      • 回滚事务:ROLLBACK
    • JDBC中的事务主要通过Connection对象来控制的
      • 开启事务
        • void setAutoCommit(boolean autoCommit) throws SQLException;
        • //设置事务是否自动提交,默认是自动提交
        • //设置事务手动提交
        • conn.setAutoCommit(false);
      • //提交事务
        • void commit() throws SQLException;
        • //提交事务
        • conn.commit()
      • 回滚事务
        • void rollback() throws SQLException;
        • //回滚事务
        • conn.rollback()
    • 事务控制的格式:
     1 Connection conn = null;//创建一个Connection
     2 try{
     3     conn = JDBCUtils.getConnection();//获取Connection
     4     conn.setAutoCommit(false);//开启事务
     5     //对数据库进行操作
     6     conn.commit();//操作成功,提交事务
     7 } catch(Exception e){
     8     e.printStackTrace();
     9     //回滚事务
    10     try {
    11         conn.rollback();
    12     } catch (SQLException e1) {
    13         e1.printStackTrace();
    14     }
    15 } finally{
    16     DBUtil.close(conn, null, null);
    17 }

    注意:在同一个事务中使用的数据库连接(Connection)必须是同一个,否则事务不起作用!

    对上面的代码进行修改

     1 //StudentDao类
     2 public static int updateAccount(Connection conn,Integer id,Integer account) {
     3     PreparedStatement ps = null;
     4     String sql = "update student set account=account+? where id=?";
     5     int i = 0;
     6     try {
     7         ps = conn.prepareStatement(sql);
     8         ps.setInt(1, account);
     9         ps.setInt(2, id);
    10         i = ps.executeUpdate();
    11     } catch (SQLException e) {
    12         e.printStackTrace();
    13     } finally{
    14         DBUtil.close(null, ps, null);
    15     }
    16     return i;
    17 }
    18 //测试类
    19 @Test
    20 public void testTransaction() {
    21     Connection conn = DBUtil.getConn();//获取连接Connection
    22     try {
    23         conn.setAutoCommit(false);//开启事务
    24         StudentDao.updateAccount(conn, 1, -100);
    25         int i=10/0;
    26         StudentDao.updateAccount(conn, 2, 100);
    27         conn.commit();//操作成功,提交事务
    28     } catch (SQLException e) {
    29         e.printStackTrace();
    30         //回滚事务
    31         try {
    32             conn.rollback();
    33         } catch (SQLException e1) {
    34             e1.printStackTrace();
    35         }
    36     } finally{
    37         DBUtil.close(conn, null, null);
    38     }
    39 }

    int i=10/0; 处抛出了错误,但是事务没有提交,并进行了回滚,所以数据库中的数据没有变,运行正常的话,可以进行正常转账。

    4、批处理和事务的结合

    实际开发中,批处理和事务常常是结合在一起使用。速度会成倍增加

     1 @Test
     2 public void testTransBatch() {
     3     Connection conn = DBUtil.getConn();
     4     PreparedStatement ps = null;
     5     try {
     6         conn.setAutoCommit(false);//开启事务
     7         String sql = "INSERT INTO student(NAME) VALUES(?)";
     8         try {
     9             ps = conn.prepareStatement(sql);
    10             for (int i = 0; i < 1000; i++) {
    11                 ps.setString(1, "stu"+i);
    12                 ps.addBatch();
    13             }
    14             long start = System.currentTimeMillis();
    15             ps.executeBatch();
    16             long end = System.currentTimeMillis();
    17             System.out.println((end-start)+"ms");
    18         } catch (SQLException e) {
    19             e.printStackTrace();
    20         }
    21         conn.commit();//提交事务
    22     } catch (SQLException e) {
    23         //回滚事务
    24         try {
    25             conn.rollback();
    26         } catch (SQLException e1) {
    27             e1.printStackTrace();
    28         }
    29         e.printStackTrace();
    30     } finally{
    31         DBUtil.close(conn, ps, null);
    32     }
    33 }

    运行时间:平均20ms左右

    sql批处理(batch)的简单使用

     DBUtil工具类--->资源目录--->工具类--->数据库操作工具类

  • 相关阅读:
    扑克牌顺子
    反转字符串
    左旋转字符串
    和为S的两个数
    C++中substr()详解
    STL库中的equal_range()
    和为S的连续正序列
    数组中只出现一次的数
    二叉树的深度
    mysql找安装路经,更改密码
  • 原文地址:https://www.cnblogs.com/lixiang1993/p/7453809.html
Copyright © 2011-2022 走看看