zoukankan      html  css  js  c++  java
  • JDBC 事务处理

    1 数据库事务介绍

    • 事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态。
    • 事务处理(事务操作):保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务**回滚(rollback)**到最初状态。
    • 为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。

    2 JDBC事务处理

    • 数据一旦提交,就不可回滚。

    • 数据什么时候意味着提交?

      • 当一个连接对象被创建时,默认情况下是自动提交事务:每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
      • **关闭数据库连接,数据就会自动的提交。**如果多个操作,每个操作使用的是自己单独的连接,则无法保证事务。即同一个事务的多个操作必须在同一个连接下。
    • JDBC程序中为了让多个 SQL 语句作为一个事务执行:

      • 调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务
      • 在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
      • 在出现异常时,调用 rollback(); 方法回滚事务

      若此时 Connection 没有被关闭,还可能被重复使用,则需要恢复其自动提交状态 setAutoCommit(true)。尤其是在使用数据库连接池技术时,执行close()方法前,建议恢复自动提交状态。

    【案例:用户AA向用户BB转账100】

    public void testJDBCTransaction() {
    	Connection conn = null;
    	try {
    		// 1.获取数据库连接
    		conn = JDBCUtils.getConnection();
    		// 2.开启事务
    		conn.setAutoCommit(false);
    		// 3.进行数据库操作
    		String sql1 = "update user_table set balance = balance - 100 where user = ?";
    		update(conn, sql1, "AA");
    
    		// 模拟网络异常
    		//System.out.println(10 / 0);
    
    		String sql2 = "update user_table set balance = balance + 100 where user = ?";
    		update(conn, sql2, "BB");
    		// 4.若没有异常,则提交事务
    		conn.commit();
    	} catch (Exception e) {
    		e.printStackTrace();
    		// 5.若有异常,则回滚事务
    		try {
    			conn.rollback();
    		} catch (SQLException e1) {
    			e1.printStackTrace();
    		}
        } finally {
            try {
    			//6.恢复每次DML操作的自动提交功能
    			conn.setAutoCommit(true);
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
            //7.关闭连接
    		JDBCUtils.closeResource(conn, null, null); 
        }  
    }
    

    其中,对数据库操作的方法为:

    
    //使用事务以后的通用的增删改操作(version 2.0)
    public void update(Connection conn ,String sql, Object... args) {
    	PreparedStatement ps = null;
    	try {
    		// 1.获取PreparedStatement的实例 (或:预编译sql语句)
    		ps = conn.prepareStatement(sql);
    		// 2.填充占位符
    		for (int i = 0; i < args.length; i++) {
    			ps.setObject(i + 1, args[i]);
    		}
    		// 3.执行sql语句
    		ps.execute();
    	} catch (Exception e) {
    		e.printStackTrace();
    	} finally {
    		// 4.关闭资源
    		JDBCUtils.closeResource(null, ps);
    
    	}
    }
    
  • 相关阅读:
    剑指Offer-30.连续子数组的最大和(C++/Java)
    剑指Offer-29.最小的K个数(C++/Java)
    UVA 1616 Caravan Robbers 商队抢劫者(二分)
    UVA 10570 Meeting with Aliens 外星人聚会
    UVA 11093 Just Finish it up 环形跑道 (贪心)
    UVA 12673 Erratic Expansion 奇怪的气球膨胀 (递推)
    UVA 10954 Add All 全部相加 (Huffman编码)
    UVA 714 Copying Books 抄书 (二分)
    UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)
    codeforecs Gym 100286B Blind Walk
  • 原文地址:https://www.cnblogs.com/James-221/p/13647462.html
Copyright © 2011-2022 走看看