zoukankan      html  css  js  c++  java
  • JDBC(六)—— 数据库事务

    数据库事务

    事务

    一组逻辑操作单元,使数据从一种状态变换到另一种状态

    事务处理

    保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。

    当在一个事务中执行多个操作时,要么所有事务都提交,要么数据库管理系统放弃所有修改,整个事务回宫到最初状态。

    数据一旦提交就不可回滚

    • DDL操作执行自动提交

    • DML默认情况下一旦执行,自动提交。可通过set autocommit = false的方式取消DML操作的自动提交

    • 关闭连接时会自动提交

    支持事物的增删改操作

    /**
    * 支持事务的增删改操作
    * @param conn
    * @param sql
    * @param args
    */
    public void update(Connection conn,String sql,Object ...args){
       PreparedStatement ps = null;
       try {
           //2.预编译sql语句,返回preparedStatement实例
           ps = conn.prepareStatement(sql);
           //3.填充占位符
           //sql占位符的个数与可变形参的长度相同,可变形参相当于一个数组
           for (int i = 0; i < args.length ; i++) {
               ps.setObject(i+1,args[i]);
          }
           //4.执行
           ps.execute();
      } catch (Exception e) {
           e.printStackTrace();
      } finally {
           //5.资源关闭
           JdbcUtils.closeResource(null,ps);
      }
    }

    使用

    public void testTransaction() {
       Connection conn = null;
       try {
           String sql1 = "update `transaction` set money = money - 100 where name = ?";
           String sql2 = "update `transaction` set money = money + 100 where name = ?";
           CommonUtils commonUtils = new CommonUtils();
           conn = JdbcUtils.getConnection();

           //取消数据的自动提交功能
           conn.setAutoCommit(false);

           commonUtils.update(conn,sql1,"why");

           commonUtils.update(conn,sql2,"wyy");
           System.out.println("转账成功");
           
           //提交数据
           conn.commit();
           
      } catch (Exception e) {
           e.printStackTrace();
           try {
               //回滚数据
               conn.rollback();
          } catch (SQLException throwables) {
               throwables.printStackTrace();
          }
      } finally {
           JdbcUtils.closeResource(conn,null);
      }
    }

    事务的ACID属性及四种隔离级别

    ACID属性

    1. 原子性(Atomicity):指事务是不可分割的单位

    2. 一致性(Consistency):事务必须使数据库从一个一致性转移到另一个一致性状态

    3. 隔离性(Isolation):指一个事务的执行不能被其他事务干扰,一个事务内部的操作及使用的数据对并发的其他事务是隔离的

    4. 持久性(Durability):指事务一旦被提交,对数据库的改变即为永久性的

    数据库并发问题

    • 脏读

      事务T1,T2

      T1读取了已经被T2更新但是没有提交的字段

      T2回滚,T1读取的内容无效

    • 不可重复读

      事务T1,T2

      T1读取了一个字段,然后T2更新了该字段.

      之后T1再次读取同一字段,值不同

    • 幻读

      事务T1,T2

      T1读取了这个表中的某些字段,T2插入了数据

      T1再次相同表的同一字段 增加了几行

    四种隔离级别

    1. READ UNCOMMITED(读未提交数据)

      允许事务读取未被其他事务提交的变更.

      问题:脏读,不可重复读,幻读

    2. READ COMMITED(读已提交数据)

      只允许事务读取已经被其他事务提交的变更,避免脏读.

      问题:不可重复的,幻读

    3. REPEATABLE READ(可重复读)

      雀稗史无可多次从一个字段中读取相同的值,在此期间,禁止其他事务对这个字段进行更新.

      问题:幻读

    4. SERIALIZABLE(串行化)

      确保十五从一个表读取相同的行,在此期间,禁止其他事务对该表进行更新操作,所有并发问题都可避免,但是性能低下.

    注:

    1. Oracle数据库支持2种事务隔离:READ UNCOMMITED(读未提交数据)和SERIALIZABLE(串行化),默认为READ UNCOMMITED(读未提交数据)

    2. Mysql 支持4种事务隔离,默认:REPEATABLE READ(可重复读)

    在MySQL用命令行设置隔离级别

    Mysql常用命令

    进入mysql

    命令行输入:mysql -u用户名 -p密码

    修改密码

    mysqladmin -u用户名 -p旧密码 password 新密码

    添加新用户并赋予相应权限

    grant select on 数据库.* to 用户名@登录主机 identified by “密码”

    显示所有数据库

    show databases

    删除数据库

    drop database <数据库名>

    设置隔离级别

    设置当前连接的隔离级别

    set transaction isolation level read committed;

    设置全局隔离级别

    set global transaction isolation level read committed;

    Java代码设置隔离级别

    conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
    public void testSelect() throws Exception {
       Connection conn = JdbcUtils.getConnection();
       //获取当前隔离级别
       System.out.println(conn.getTransactionIsolation());
       //取消自动提交数据
       conn.setAutoCommit(false);
       //设置数据库隔离级别
       conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
       String sql = "select username,password,reg_date regDate from user where username = ?";
       User user = commonUtils.queryForDifference(conn, User.class, sql, "why");
       System.out.println(user);
    }

    @Test
    public void testUpdae() throws Exception {
       Connection conn = JdbcUtils.getConnection();
       //取消自动提交
       conn.setAutoCommit(false);
       String sql = "update user set username = ? where username = ?";
       commonUtils.update(conn,sql,"love","why");
       Thread.sleep(15000);
       System.out.println("修改结束");
    }

     

  • 相关阅读:
    操作系统中线程中所需内存来源哪里
    【转】在单片机(MCU)上运行Qt
    【转】Qt QtCreator 所有版本官方下载地址
    emwin之BUTTON控件显示位图和流位图出现卡顿延迟的情况
    【转】8段数码管引脚图,8段数码管动态显示详解
    emwin之窗口ID的唯一性
    KEIL之工程单独文件属性修改
    emwin之在中断服务程序中创建窗口的结果
    emwin之创建窗口与窗口回调函数的句柄是一致的
    【转】C语言堆栈入门——堆和栈的区别
  • 原文地址:https://www.cnblogs.com/whystudyjava/p/14135410.html
Copyright © 2011-2022 走看看