一、事务介绍
事务:一组逻辑操作单元,使数据从一种状态变换到另一个状态
事务处理(事务操作):保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方 式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态
为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:当它全部完成时,数据的一致性可 以保持,而当这个单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态
二、JDBC中对事务的处理
数据一旦提交,就不可回滚
数据什么时候意味着提交?
当一个连接对象被创建时,默认情况下自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能回滚
关闭数据库连接,数据就会自动的提交。如果多个操作,每个操作使用的是自己单独的连接,则无法保证 事务。即同一个事务的多个操作必须在同一个连接下
JDBC程序中为了让多个SQL语句作为一个事务执行
● 调用Connection对象的 setAutoCommit(false); 以取消自动提交事务
● 在所有的SQL语句都成功执行后,调用 commit(); 方法提交事务
● 在出现异常时,调用 rollback(); 方法回滚事务
● 在使用数据库连接池技术时,执行close()方法前,建议使用 setAutoCommit(true); 恢复自动提交状态
使用事务后的通用增删改查操作:
public void update(Connection conn,String sql,Object...obj){ PreparedStatement ps=null; try{ //1.预编译sql语句,返回PreparedStatement实例 ps=conn.prepareStatement(sql); //2.填充占位符 for(int i=0;i<obj.length;i++){ ps.setObject(i+1,obj[i]); } //3.执行操作 ps.execute(); }catch(Exception e){ e.printStackTrace(); }finally{ //5.释放资源 JDBCUtils.closeConnection(null,ps); } }
事务使用实例:
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); } }
三、事务的ACID属性
原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
一致性(Consistency)事务必须使数据库从一个一致性状态变换到另外一个一致性状态
隔离性(Isolation)事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的 数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰
持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其 他操作和数据库故障不应该对其有任何影响