Java开发基础-JDBC-核心概念—02

在JDBC中对事物的处理方式:

Java JDBC事务机制

 首先,我们来看看现有JDBC操作会给我们打来什么重大问题,比如有一个业务:当我们修改一个信息后再去查询这个信息,看是这是一个简单的业务,实现起来也非常容易,但当这个业务执行中出错时,问题自然就出现了,比如当我们执行了一个修改过程中网络突然断掉或电脑死机掉电,,在问题修复后我们再执行查询,看到的信息就有可能与我们修改想要的不同【出错就不做修改,否则就修改】,为了解决这一问题,我们必须引入JDBC事务机制

下面通过简单的转账业务实例演示:

创建演示实例需要的数据库表

create table accounts (
	id varchar2(20),
	name varchar2(30),
	money number(11,2)
);

insert into accounts values('00001','张三',8000.0);
insert into accounts values('00002','李四',4000.0);
commit;

1.不使用事物管理:

public class TestDay03 {
	
	@Test
	public void test21(){
		//假设用户在ATM上输入了如下信息
		String payId = "00001";//付款账号
		String recId = "00002";//收款账号
		double mny = 1000.0;//转账金额
		
		Connection conn = null;
		try {
			conn = DBUtil.getConnection();
			//1.验证收款方账号是否存在
			String sql = "select * from ACCOUNTS "
					    +"where id= ?";
			PreparedStatement ps = conn.prepareStatement(sql);
			ps.setString(1, recId);
			ResultSet rs  = ps.executeQuery();
			if(!rs.next()){
				System.out.println("收款方账户不存在!");
				throw new SQLException("收款方账户不存在!");
			}
			//记录收款方余额,便于后面转账时+余额
			double recMoney = rs.getDouble("money");
			//2.验证付款方账户余额是否够用
			sql = "select * from ACCOUNTS "
				 +"where id= ?";
			ps = conn.prepareStatement(sql);
			ps.setString(1, payId);
			rs = ps.executeQuery();
			
			rs.next();
			double payMoney = rs.getDouble("money");
			
			
			if(payMoney<mny){
				System.out.println("余额不足!");
				throw new SQLException("余额不足!");
			}
			
			
			//3.付款方账户-n元
			sql ="update ACCOUNTS set "
				 +"money=? where id=?";
			ps = conn.prepareStatement(sql);
			ps.setDouble(1, payMoney-mny);
			ps.setString(2, payId);
			ps.executeUpdate();
			
			//假设此处有个错误
			Integer.valueOf("abc");
			
			//4.收款方账户+n元
			sql = "update accounts set "
				 +"money = ? where id=?";
			ps = conn.prepareStatement(sql);
			ps.setDouble(1, recMoney+mny);
			ps.setString(2, recId);
			ps.executeUpdate();
			
		} catch (Exception e) {	
			e.printStackTrace();
			throw new RuntimeException("转账失败!");
		}finally{
			DBUtil.close(conn);
		}
	}
	
}

使用Junit方式运行程序,可以看到控制台有报错信息


再看下数据库中数据是否收到影响导致数据不一致,很明显数据第一条数据修改了,而第二条却没有,两者之和少了1000


2.使用事物管理:

public class TestDay03 {
	
	/**
	 * 模拟转账 -学习jdbc中对事物的处理
	 * 1.验证收款方账号是否存在
	 * 2.验证付款方账户余额是否够用
	 * 3.付款方账户-n元
	 * 4.收款方账户+n元
	 */
	@Test
	public void test2(){
		//假设用户在ATM上输入了如下信息
		String payId = "00001";//付款账号
		String recId = "00002";//收款账号
		double mny = 1000.0;//转账金额
		
		Connection conn = null;
		try {
			conn = DBUtil.getConnection();
			//1.验证收款方账号是否存在
			String sql = "select * from ACCOUNTS "
					    +"where id= ?";
			PreparedStatement ps = conn.prepareStatement(sql);
			ps.setString(1, recId);
			ResultSet rs  = ps.executeQuery();
			if(!rs.next()){
				System.out.println("收款方账户不存在!");
				throw new SQLException("收款方账户不存在!");
			}
			//记录收款方余额,便于后面转账时+余额
			double recMoney = rs.getDouble("money");
			//2.验证付款方账户余额是否够用
			sql = "select * from ACCOUNTS "
				 +"where id= ?";
			ps = conn.prepareStatement(sql);
			ps.setString(1, payId);
			rs = ps.executeQuery();
			
			rs.next();
			double payMoney = rs.getDouble("money");
			
			
			if(payMoney<mny){
				System.out.println("余额不足!");
				throw new SQLException("余额不足!");
			}
			
			//设置手动管理事物(取消自动提交事物)
			conn.setAutoCommit(false);
			
			//3.付款方账户-n元
			sql ="update ACCOUNTS set "
				 +"money=? where id=?";
			ps = conn.prepareStatement(sql);
			ps.setDouble(1, payMoney-mny);
			ps.setString(2, payId);
			ps.executeUpdate();
			
			//假设此处有个错误
			Integer.valueOf("abc");
			
			//4.收款方账户+n元
			sql = "update accounts set "
				 +"money = ? where id=?";
			ps = conn.prepareStatement(sql);
			ps.setDouble(1, recMoney+mny);
			ps.setString(2, recId);
			ps.executeUpdate();
			
			//当转账流程正常结束时统一提交事物
			conn.commit();
		} catch (Exception e) {	
			//当转账过程中发生异常时回滚事物
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
				throw new RuntimeException("事物回滚失败!");
			}
			
			e.printStackTrace();
			throw new RuntimeException("转账失败!");
		}finally{
			DBUtil.close(conn);
		}
	}
	
}

使用Junit方式运行程序,可以看到控制台有报错信息


再看下数据库中数据是否收到影响导致数据不一致,很明显没有,两条数据都没改变,之和也没变【程序错误,事物回滚了】


取消程序中的错误模拟,再次运行程序,控制台没有报错,数据库中数据修改正确!


猜你喜欢

转载自blog.csdn.net/coder_boy_/article/details/80642034