- 在我的理解中,事务是一个很普遍的概念,即任何一条sql语句的执行都是一个事务的处理过程,都包括了:注册驱动,创建连接,创建sql语句,执行sql语句,最后就是资源的释放。整个的这样一个过程就是事务的处理过程。以下是本人通过搜索引擎检索到的一些我认为比较好的概念:
事务是一个不可分割的工作逻辑单元
转帐过程就是一个事务。
它需要两条UPDATE语句来完成,这两条语句是一个整体,如果其中任一条出现错误,则整个转帐业务也应取消,两个帐户中的余额应恢复到原来的数据,从而确保转帐前和转帐后的余额不变,
事务必须具备以下四个属性,简称ACID 属性:
原子性(Atomicity):事务是一个完整的操作。事务的各步操作是不可分的(原子的);要么都执行,要么都不执行
一致性(Consistency):当事务完成时,数据必须处于一致状态
隔离性(Isolation):对数据进行修改的所有并发事务是彼此隔离的,这表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务
永久性(Durability):事务完成后,它对数据库的修改被永久保持,事务日志能够保持事务的永久性
connection.setAutoCommit(false);//打开事务
connection.commit();//提交事务
connection.rollback();//回滚事务
现在我有这样的需求:我要从id为1的用户那里扣除10块钱,然后加到id为2的用户那里去,但是如果中间出异常了,怎么办呢?
修改前代码:
- 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);
- }
- }
为了避免发生这样的情况再次发生,我们可以把执行加钱和扣钱的语句放到一个事务里处理,一旦出现异常情况就不要commit整个事务,确保帐户里面的钱是正确的。
修改后代码:
- 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);
- }
- }