事务_数据库连接池_DBUtils_MVC

事务:

  1、事务(Transaction):指的是一组操作逻辑,里面包含了很多个单一的操作逻辑。如果有一个逻辑失败,那么无论其它逻辑是否成功,都算失败。

  2、为什么需要事务:

    为了保证一组关联逻辑的全部正确执行。举例:银行转账

  3、如何开启事务,以及事务的两种结果处理:

    开启事务:start transaction;

    两种结果处理:commit / rollback

  4、示例:

    关闭自动提交

    

 

 

    演示事务:

    

@Test
    public void testTransaction(){
        
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtil.getConn();
            
            //连接,事务默认就是自动提交的。 关闭自动提交。
            conn.setAutoCommit(false);
            
            String sql = "update account set money = money - ? where id = ?";
            ps = conn.prepareStatement(sql);
            
            //扣钱, 扣ID为1 的100块钱
            ps.setInt(1, 100);
            ps.setInt(2, 1);
            ps.executeUpdate();
            
            
            int a = 10 /0 ;
            
            //加钱, 给ID为2 加100块钱
            ps.setInt(1, -100);
            ps.setInt(2, 2);
            ps.executeUpdate();
            
            //成功: 提交事务。
            conn.commit();
            
        } catch (SQLException e) {
            try {
                //事变: 回滚事务
                conn.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
            
        }finally {
            JDBCUtil.release(conn, ps, rs);
        }
    }

  5、事务特性:(ACID)

    原子性:事务中包含的逻辑,不可分割。

    一致性:事务执行前后。数据完整性

    隔离性:事务在执行期间不应该受到其他事务的影响

    持久性:事务执行成功,那么数据应该持久保存到磁盘上。

  6、事务隔离级别以及对应的安全隐患:

    读未提交(read uncommitted):脏读

    读已提交(read committed):解决脏读,引发不可重复的

    可重复度(repeatable read):解决脏读,不可重复的,引发幻读

    可串行化(serializable):解决脏读,不可重复读,幻读  

    安全隐患:

    读: 

      脏读
        一个事务读到了另一个事务未提交的数据
      不可重复读
        一个事务读到了另一个事务已提交的数据,造成前后两次查询结果不一致
      幻读
        一个事务读到了另一个事务insert的数据 ,造成前后查询结果不一致 。

    写:

      丢失更新。

  7、事务隔离级别排序:

    按效率(高->低):读未提交  > 读已提交  > 可重复读  > 可串行化

    按拦截程度(高->低):可串行化 > 可重复读 > 读已提交 >  读未提交

  8、事务只是针对连接连接对象,如果再开一个连接对象,那么那是默认的提交。

  9、mySql 默认的隔离级别是 可重复读

       Oracle 默认的隔离级别是 读已提交

  10、解决丢失更新的方式:

     悲观锁:

 

     乐观锁:

 

 

 

 

数据库连接池:

  DBCP:

  1、不使用配置文件的方式:

       Connection conn = null;
            PreparedStatement ps = null;
            try {
                //1. 构建数据源对象
                BasicDataSource dataSource = new BasicDataSource();
                //连的是什么类型的数据库, 访问的是哪个数据库 , 用户名, 密码。。
                dataSource.setDriverClassName("com.mysql.jdbc.Driver");
                dataSource.setUrl("jdbc:mysql://localhost/bank");
                dataSource.setUsername("root");
                dataSource.setPassword("root");
                //2. 得到连接对象
                conn = dataSource.getConnection();
                String sql = "insert into account values(null , ? , ?)";
                ps = conn.prepareStatement(sql);
                ps.setString(1, "admin");
                ps.setInt(2, 1000);
                
                ps.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JDBCUtil.release(conn, ps);
            }

  2、使用配置文件方式:

     Connection conn = null;
        PreparedStatement ps = null;
        try {
            BasicDataSourceFactory factory = new BasicDataSourceFactory();
            Properties properties = new Properties();
            InputStream is = new FileInputStream("src//dbcpconfig.properties");
            properties.load(is);
            DataSource dataSource = factory.createDataSource(properties);
            //2. 得到连接对象
            conn = dataSource.getConnection();
            String sql = "insert into account values(null , ? , ?)";
            ps = conn.prepareStatement(sql);
            ps.setString(1, "liangchaowei");
            ps.setInt(2, 100);
            
            ps.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtil.release(conn, ps);
        }

  CP30:

  1、不适用配置文件

     Connection conn = null;
        PreparedStatement ps = null;
        try {
            //1. 创建datasource
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            //2. 设置连接数据的信息
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            dataSource.setJdbcUrl("jdbc:mysql://localhost/bank");
            dataSource.setUser("root");
            dataSource.setPassword("root");
            //2. 得到连接对象
            conn = dataSource.getConnection();
            String sql = "insert into account values(null , ? , ?)";
            ps = conn.prepareStatement(sql);
            ps.setString(1, "admi234n");
            ps.setInt(2, 103200);
            
            ps.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtil.release(conn, ps);
        }

  2、使用配置文件(注意:CP30的配置文件可以用properties或者xml,常用xml)

        Connection conn = null;
        PreparedStatement ps = null;
        try {
            //就new了一个对象。
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            
            //2. 得到连接对象
            conn = dataSource.getConnection();
            String sql = "insert into account values(null , ? , ?)";
            ps = conn.prepareStatement(sql);
            ps.setString(1, "wangwu2");
            ps.setInt(2, 2600);
            
            ps.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtil.release(conn, ps);
        }

DBUtils:

  1、增删改

        //dbutils 只是帮我们简化了CRUD 的代码, 但是连接的创建以及获取工作。 不在他的考虑范围
        QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
    
        //增加
        //queryRunner.update("insert into account values (null , ? , ? )", "aa" ,1000);
        
        //删除
        //queryRunner.update("delete from account where id = ?", 5);
        
        //更新
        //queryRunner.update("update account set money = ? where id = ?", 10000000 , 6);

  2、查询

    1)匿名内部类方式,自定义返回值的接收配置

     QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
        Account  account =  queryRunner.query("select * from account where id = ?", new ResultSetHandler<Account>(){
            @Override
            public Account handle(ResultSet rs) throws SQLException {
                Account account  =  new Account();
                while(rs.next()){
                    String name = rs.getString("name");
                    int money = rs.getInt("money");
                    
                    account.setName(name);
                    account.setMoney(money);
                }
                return account;
            }
         }, 6);
        System.out.println(account.toString());

    2)使用框架写好的实现类

     查询单个对象
        QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
        //查询单个对象
        Account account = queryRunner.query("select * from account where id = ?", 
                new BeanHandler<Account>(Account.class), 8);
    
      查询多个对象
        QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
        List<Account> list = queryRunner.query("select * from account ",
                new BeanListHandler<Account>(Account.class));

  3、ResultSetHandler 常用的实现类

    BeanHandler, 查询到的单个数据封装成一个对象
    BeanListHandler, 查询到的多个数据封装 成一个List<对象>

    ArrayHandler, 查询到的单个数据封装成一个数组
    ArrayListHandler, 查询到的多个数据封装成一个集合 ,集合里面的元素是数组。

    MapHandler, 查询到的单个数据封装成一个map
    MapListHandler,查询到的多个数据封装成一个集合 ,集合里面的元素是map。

 

 需要对应的jar包请留言

posted @ 2022-02-24 21:25  CGGirl  阅读(53)  评论(0编辑  收藏  举报