JDBC03(事务管理、ThreadLocal)

Part01:事务管理

1、事务概述:

  • 事务:指的是逻辑上的一组操作(多条sql语句),组成这组操作的各个单元要么全部成功,要么全部失败。
  • 事务作用:保证在一个事务中多次操作要么全部成功,要么全部失败;
  • 例如转账的转账方和收款方;

2、MySQL事务操作:

  • start transaction:开启事务(Java中用setAutoCommit(false)方法)
  • commit:提交事务
  • rollback:回滚事务

3、使用JDBC自写工具类模拟转账功能:

public class JDBCAccountDemo {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        try {
            //获取连接
            connection = JDBCUtils.getConnection();
            //在所有操作之前执行事务
            connection.setAutoCommit(false);//设置自动提交事务为false(就是开启事务)
            statement = connection.createStatement();
            String sql1 = "update account set money = money - 100 where name = '李四'";
            String sql2 = "update account set money = money + 100 where name = '张三'";
            int rows1 = statement.executeUpdate(sql1);
            //模拟出现异常,转出成功,转入被异常阻断
            //System.out.println(1/0);
            int rows2 = statement.executeUpdate(sql2);
            //在所有操作之后,提交事务
            connection.commit();
            if(rows1 > 0 && rows2 > 0){
                System.out.println("转账成功");
            }
        } catch (SQLException e) {
            //出现异常,回滚事务
            try {
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            //关闭资源
            JDBCUtils.closeAll(connection,statement,null);
        }

    }
}

4、使用DBUtils工具类实现转账案例:

  • QueryRunner的两个构造:
    • public QueryRunner(DataSource);//不支持事务操作,因为不能确定从连接池获取的是同一个连接
      • 方法:
        • update(String sql, Object … params)
        • query(String sql,ResultSetHandler handler,Object … params)
    • public QueryRunner( );//支持事务操作
      • 方法:
        • update(Connection con,String sql, Object … params)

        • query(Connection con,String sql,ResultSetHandler handler,Object … params)

          //1.创建QueryRunner对象
            QueryRunner qr = new QueryRunner();
            Connection con = null;
            try {
                con = C3P0Utils.getConnection();//获取连接
                //开启事务
                con.setAutoCommit(false);
                //2.执行sql语句
                int rows1 = qr.update(con, "update account set money=money-? where name=?", 100, "张三");
                System.out.println(1 / 0);//模拟出现异常
                int rows2 = qr.update(con, "update account set money=money+? where name=?", 100, "李四");
                //提交事务
                con.commit();
                if (rows1 > 0 && rows2 > 0) {
                    System.out.println("转账成功");
                }
            } catch (Exception e) {
                try {
                    //回滚事务
                    con.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
                System.out.println("转账出现问题,程序回滚");
            } finally {
                try {
                    con.close();//关闭资源
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
          }
          

5、三层思想:高内聚、低耦合

  • DAO层:(date access object)数据访问层(处理数据库),一般抛出异常
  • Service层:业务层(处理业务逻辑),一般捕获异常
  • Web层/view层:给用户看的

6、分层的目的:

  • 解耦:减少层与层之间的关系
  • 增强可维护性
  • 增强可扩展性
  • 增强可重用性

7、不同层次包名命名规范:

  • com.megu 公司域名倒写
  • com.megu.dao dao层
  • com.megu.service service层
  • com.megu.domain javabean
  • Com.megu.utils 工具
  • com.megu.web/view web层

8、事务的特性:

  • 原子性:强调事务的不可分割,多条语句要么都成功,要么都失败
  • 一致性:强调的是事务执行的前后,数据要保持一致
  • 隔离性:一个事务的执行不应该受到其他事务的干扰
  • 持久性:事务一旦结束(提交/回滚),数据就持久保持到了数据库

9、如果不考虑事务的隔离性,可能引发以下安全性问题:

  • 脏读:一个事务读到另一个事务还没有提交的数据
  • 不可重复读:一个事务读到另一个事务以及提交的update的数据,导致在当前的事务中多次查询结果不一致;
  • 虚读/幻读:一个事务读到另一个已经提交的insert的数据,导致当前的事务中多次的查询结果不一致;

10 、设置事务的隔离级别:

  • 1 read uncommitted :未提交读,以上三种安全问题都有可能发生
  • 2 read committed:已提交读,可以避免脏读,但是其他两种问题都有可能发生(Oracle默认)
  • 4 repeatable read:可重复读,可以避免脏读和不可重复读的问题,但是虚读有可能发生(MySQL默认);
  • 8 serializable:串行化的,可以避免以上三种问题的发生
    注意⚠️:级别越高,越安全,效率越低

11、MySQL中查看当前事务级别:SELECT @@TX_ISOLATION;
更改当前事务隔离级别:SET TRANSACTION ISOLATION LEVEL ….

Part02:ThreadLocal

1、ThreadLocal:线程局部变量

  • 作用:为每一个线程,提供一个独立的存储数据空间,只能由该线程访问
  • 底层:ThreadLocal类实际上在内部封装了一个Map集合Map<Thread,Object>
  • 方法:
    • get( );//以当前线程对象为键,从类内部的Map中获取值
    • set(Object);//给当前线程对象设置值,保存到map集合中
  • 结论:ThreadLocal能保证哪个线程的数据只能由那个线程取出,别的线程无法取出;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值