数据库中事务概念的定义

事务(TRANSACTION)是作为单个逻辑工作单元执行的一系列操作

 

这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行
事务是一个不可分割的工作逻辑单元

转帐过程就是一个事务。
它需要两条UPDATE语句来完成,这两条语句是一个整体,如果其中任一条出现错误,则整个转帐业务也应取消,两个帐户中的余额应恢复到原来的数据,从而确保转帐前和转帐后的余额不变,

事务必须具备以下四个属性,简称ACID 属性:
原子性(Atomicity):事务是一个完整的操作。事务的各步操作是不可分的(原子的);要么都执行,要么都不执行
一致性(Consistency):当事务完成时,数据必须处于一致状态
隔离性(Isolation):对数据进行修改的所有并发事务是彼此隔离的,这表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务
永久性(Durability):事务完成后,它对数据库的修改被永久保持,事务日志能够保持事务的永久性 connection.setAutoCommit(false);//打开事务 connection.commit();//提交事务 connection.rollback();//回滚事务

如果根据上面三条语句的注释,我觉得我最初的理解还是不足的地方的。 现在我有这样的需求:我要从id为1的用户那里扣除10块钱,然后加到id为2的用户那里去,但是如果中间出异常了,怎么办呢? 修改前代码:

  1. static void test() throws SQLException { 
  2.         Connection conn = null
  3.         Statement st = null
  4.         ResultSet rs  = null
  5.         try { 
  6.             conn = JdbcUtil.getConnection(); 
  7.             st = conn.createStatement();             
  8.             String sql = "update user set money = money -10 where id =1"
  9.             st.executeUpdate(sql); 
  10.             sql = "select money from user where id = 2"
  11.             rs = st.executeQuery(sql); 
  12.             float money = 0.0f; 
  13.             if (rs.next()) { 
  14.                 money = rs.getFloat("money"); 
  15.             } 
  16.              
  17.             if(money > 200) { 
  18.                 throw new RuntimeException("已经超过了最大值!"); 
  19.             } 
  20.             sql = "update user set money = money + 10 where id =2"
  21.             st.executeUpdate(sql); 
  22.         } finally { 
  23.             JdbcUtil.free(rs, st, conn); 
  24.         } 
  25.     } 
static void test() throws SQLException {
		Connection conn = null;
		Statement st = null;
		ResultSet rs  = null;
		try {
			conn = JdbcUtil.getConnection();
			st = conn.createStatement();			
			String sql = "update user set money = money -10 where id =1";
			st.executeUpdate(sql);
			sql = "select money from user where id = 2";
			rs = st.executeQuery(sql);
			float money = 0.0f;
			if (rs.next()) {
				money = rs.getFloat("money");
			}
			
			if(money > 200) {
				throw new RuntimeException("已经超过了最大值!");
			}
			sql = "update user set money = money + 10 where id =2";
			st.executeUpdate(sql);
		} finally {
			JdbcUtil.free(rs, st, conn);
		}
    }

这个方法在被调用的时候,发现id为1的用户的钱被扣了,但是id为2的钱在被增加,原因就是在这个处理的过程中,由于出现了异常导致后面的语句就不再被正常的执行了,这个显然是有问题的,谁都不愿意看到说:原本想还同学的钱,发现自己的钱打过去之后,自己卡里的款被扣了,但是同学说他没收到钱。这个银行是要负责的。 为了避免发生这样的情况再次发生,我们可以把执行加钱和扣钱的语句放到一个事务里处理,一旦出现异常情况就不要commit整个事务,确保帐户里面的钱是正确的。 修改后代码:

  1. static void test() throws SQLException { 
  2.         Connection conn = null
  3.         Statement st = null
  4.         ResultSet rs  = null
  5.         try { 
  6.             conn = JdbcUtil.getConnection(); 
  7.             st = conn.createStatement(); 
  8.             conn.setAutoCommit(false);//开启一个事务 
  9.             String sql = "update user set money = money -10 where id =1"
  10.             st.executeUpdate(sql); 
  11.             sql = "select money from user where id = 2"
  12.             rs = st.executeQuery(sql); 
  13.             float money = 0.0f; 
  14.             if (rs.next()) { 
  15.                 money = rs.getFloat("money"); 
  16.             } 
  17.              
  18.             if(money > 200) { 
  19.                 throw new RuntimeException("已经超过了最大值!"); 
  20.             } 
  21.             sql = "update user set money = money + 10 where id =2";//这样就能够正常的执行一个事务了。 
  22.             st.executeUpdate(sql); 
  23.             conn.commit();//提交事务。 
  24.         } catch (SQLException e) { 
  25.             if (conn != null) { 
  26.                 conn.rollback();//回滚 
  27.             } 
  28.             throw e; 
  29.         } finally { 
  30.             JdbcUtil.free(rs, st, conn); 
  31.         } 
  32.     } 
static void test() throws SQLException {
		Connection conn = null;
		Statement st = null;
		ResultSet rs  = null;
		try {
			conn = JdbcUtil.getConnection();
			st = conn.createStatement();
			conn.setAutoCommit(false);//开启一个事务
			String sql = "update user set money = money -10 where id =1";
			st.executeUpdate(sql);
			sql = "select money from user where id = 2";
			rs = st.executeQuery(sql);
			float money = 0.0f;
			if (rs.next()) {
				money = rs.getFloat("money");
			}
			
			if(money > 200) {
				throw new RuntimeException("已经超过了最大值!");
			}
			sql = "update user set money = money + 10 where id =2";//这样就能够正常的执行一个事务了。
			st.executeUpdate(sql);
			conn.commit();//提交事务。
		} catch (SQLException e) {
			if (conn != null) {
				conn.rollback();//回滚
			}
			throw e;
		} finally {
			JdbcUtil.free(rs, st, conn);
		}
    }

这样子改好之后,当出现异常的时候,id =1 的用户的钱也不会被多扣,id =2 的用户也不会无缘无故的多出一些钱来,如果没有异常出现的时候,转账业务就会正确的执行。

所以事实上我也并没有错,一条语句就是一个事务的处理过程,只是当我们什么都没有写的时候,默认用的就是sql语句执行前开启事务,执行完后,提交事务。但是,由于业务的需要我们往往需要自己去控制事务的开启和结束过程。

转载于:https://www.cnblogs.com/wuyanbin/p/3388189.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值