• Spring框架——批处理(batch)和事务(Transaction)


    批处理(batch)

    批处理(batch)------------>好比快递员【不能一件一件的送快递】
    - 批处理指的是一次操作中执行多条SQL语句
    - 批处理相比于一次一次执行效率会提高很多

    - 批处理主要是分两步:
      1.将要执行的SQL语句保存
      2.执行SQL语句

    - Statement和PreparedStatement都支持批处理操作,这里我们只需要掌握PreparedStatement的批处理方式:
    - 方法:
      void addBatch()
    - 将要执行的SQL先保存起来,先不执行
    - 这个方法在设置完所有的占位符之后调用
      int[] executeBatch()
    - 这个方法用来执行SQL语句,这个方法会将批处理中所有SQL语句执行

    - mysql默认批处理是关闭的,所以我们还需要去打开mysql的批处理:
      rewriteBatchedStatements=true
    我们需要将以上的参数添加到mysql的url地址中

    - 注意:低版本的mysql-jdbc驱动也不支持批处理,一般都是在修改的时候使用批处理,查询的时候不使用!


    案例演示:
    1.创建一张新的数据表

    CREATE TABLE t_emp(
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(50)
    )
    

      

    2.反复打开数据库客户端,插入语句【相当于每次获取一个connection连接,执行executeUpdate语句】

    INSERT INTO t_emp(NAME) VALUES('张三');
    SELECT * FROM t_emp;


    3.引出批处理--->执行效率高,资源利用率好!

    @Test//测试批处理
    public void testBatch(){
    //向t_emp表中插入10000条数据
    
      //准备两个变量
      Connection connection = null;
      PreparedStatement ps = null;
    
      try {
        //获取数据库连接
        connection=JDBCUtil.getConnection();
        //准备SQL模板
        String sql = "INSERT INTO t_emp(NAME) VALUES(?)";
        //获取PrepareStatement
        ps = connection.prepareStatement(sql);
        //创建一个for循环,来设置占位符
        for(int i = 0; i < 10000 ;i++){
          //填充占位符
          ps.setString(1,"emp"+i);
          //添加到批处理方法中,调用无参的,有参的是Statement来调用的!
          ps.addBatch();
        } 
        //获取一个时间戳
        long start = System.currentTimeMillis();
        //执行批处理
        ps.executeBatch();
        //获取一个时间戳
        long end = System.currentTimeMillis();
        System.out.println("共花费了:"+(end-start));
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    

      

    事务(Transaction)

    演示银行转账的功能:
    1.创建一张表示账号的表

    CREATE TABLE t_account(
    id INT PRIMARY KEY AUTO_INCREMENT,
    a_name VARCHAR(50),
    balance DECIMAL(11,2)
    )
    


    2.向表中插入几个用户

    INSERT INTO t_account(id,a_name,balance) VALUES(NULL,'sunwukong',1000);
    INSERT INTO t_account(id,a_name,balance) VALUES(NULL,'zhubajie',1000);
    INSERT INTO t_account(id,a_name,balance) VALUES(NULL,'shaheshang',1000);
    SELECT * FROM t_account;
    


    3.sunwukong向shaheshang转账100元
    从sunwukong的账号减去100元

    UPDATE t_account SET balance = balance - 100 WHERE a_name='sunwukong';

    给shaheshang的账号加上100元

    UPDATE t_account SET balance = balance +100 WHERE a_name = 'shaheshang';
    


    重新设置为1000元:

    UPDATE t_account SET balance =1000;
    


    4.从java代码中演示上面的案例:
    1.创建Dao类

    public class AcountDao {	
      public void update(String name,double money){
        //准备两个变量
        Connection conn = null;
        PreparedStatement ps = null;
        //准备SQL模板
        String sql = "UPDATE t_account SET balance = balance + ? WHERE a_name = ?";
    
        try {
          conn = JDBCUtil.getConnection();
          //获取PreparedStatement
          ps = conn.prepareStatement(sql);
          //填充占位符
          ps.setDouble(1, money);
          ps.setString(2, name);
    
          //执行SQL语句
          ps.executeUpdate();
    
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }finally{
          JDBCUtil.close(conn, ps, null);
        }
      }
    }
    

      


    2.测试该DAO

    public class TestTransaction {
      private AcountDao accountDao = new AcountDao();
    
      @Test
      public void test() {
        //从sunwukong账户向shaheshang账户转账100元!
        //1.从sunwukong账户扣除100元
        accountDao.update("sunwukong", -100);
        //2.向shaheshang账户添加100元
        accountDao.update("shaheshang", 100);
      }
    }
    

      


    显然上面是可以正常执行的!
    但是如果上面的程序在suwukong减去100元之后,shaheshang加钱之前,出现了异常,如下所示:

    //从sunwukong账户向shaheshang账户转账100元!
    //1.从sunwukong账户扣除100元
    accountDao.update("sunwukong", -100);
    int i =10/0;//添加一个异常
    //2.向shaheshang账户添加100元
    accountDao.update("shaheshang", 100);
    



    - 在开发中我们的一个业务往往需要同时操作多个表,这些操作往往是不可分割,业务中的对数据库的多次操作,
    要么同时成功,要么全都失败。

    - 事务的特性(ACID):
    原子性(atomicity)
    一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。

    一致性(consistency)
    事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

    隔离性(isolation)
    一个事务的执行不能被其他事务干扰。
    即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

    持久性(durability)
    持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。
    接下来的其他操作或故障不应该对其有任何影响。


    - 操作事务的基本步骤:
    1.开启事务
    - 开启事务以后,我们只后的所有操作将都会在同一个事务当中
    2.操作数据库
    - 开启事务以后再去操作数据库,所有操作将不会直接提交到数据库中
    3.提交事务
    - 将修改应用到数据库
    4.回滚事务
    - 数据库操作过程中出现异常了,回滚事务,回滚事务以后,数据库变成开启事务之前的状态


    - mysql中的事务控制
    #开启事务
    START TRANSACTION
    #回滚事务
    ROLLBACK
    #提交事务
    COMMIT

    - JDBC中的事务主要通过Connection对象来控制的
    1.开启事务
    void setAutoCommit(boolean autoCommit) throws SQLException;
    - 设置事务是否自动提交,默认是自动提交
    - 设置事务手动提交
    conn.setAutoCommit(false);

    2.提交事务
    void commit() throws SQLException;
    - 提交事务
    conn.commit()

    3.回滚事务
    void rollback() throws SQLException;
    - 回滚事务
    conn.rollback()

    - 事务控制的格式:

    //创建一个Connection
    Connection conn = null;
    
    try{
      //获取Connection
      conn = JDBCUtils.getConnection();
      //开启事务
      conn.setAutoCommit(false);
      //对数据库进行操作
      //操作成功,提交事务
      conn.commit();
    }catch(Exception e){
      e.printStackTrace();
      //回滚事务
      try {
        conn.rollback();
      } catch (SQLException e1) {
        e1.printStackTrace();
      }
    }finally{
      JDBCUtils.close(conn, null, null);
    }
    



    - 注意:我们在同一个事务中使用的数据库连接(Connection)必须是同一个,否则事务还是不作用!
    所以此时原来的AcountDAO中的update方法要改为如下所示:

    public class AcountDao {	
      public void update(Connection conn,String name,double money){
        //准备两个变量
        PreparedStatement ps = null;
        //准备SQL模板
        String sql = "UPDATE t_account SET balance = balance + ? WHERE a_name = ?";
        
        try {
          //获取PreparedStatement
          ps = conn.prepareStatement(sql);
          //填充占位符
          ps.setDouble(1, money);
          ps.setString(2, name);
        
          //执行SQL语句
          ps.executeUpdate();
    
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }finally{
          //此时也不能在这里关闭数据库连接了,而是在外边统一关闭
          JDBCUtil.close(null, ps, null);
        }
      }
    }
    

      

  • 相关阅读:
    简单的MsChart使用与遇到的麻烦
    SQLServer中case when 与列拼接
    关于集成单点登录问题
    IIS部署网站后,只有本服务器才能登录
    获取本周的周一日期与本周的周日日期
    34个漂亮的应用程序后台管理系统界面(系列二)
    2011年最佳免费 PSD 用户界面素材揭晓
    编程你使用快捷键了吗?
    汉字转全拼音函数优化方案(SQLServer),值得你看看
    WinForm企业应用框架设计【四】动态创建业务窗体
  • 原文地址:https://www.cnblogs.com/Mr-zhaoz/p/7455040.html
Copyright © 2020-2023  润新知