介绍
假如A和B为同一个事务操作,A操作完成时,数据库等遇到一些异常,无法完成B操作,此时系统会自动删除已完成的操作,避免造成损失。保证数据库多个操作,要么全部成功,要么全部失败。
举例
问题:假如在一个银行管理系统中,A向B转钱,A刚转出去,此时遇到断电或者数据库崩溃,A转钱操作此时已经完成,但是B收钱操作未进行。这时候就会产生麻烦
演示
开启事务:con.setAutoCommit(false); true自动提交 false手动提交
提交事务(手动提交):con.commit(); 开启事务与提交事务之间的操作都为事务操作,如果期间有任何操作为执行成功,则期间所有的操作都无效
public static void transferAccounts(String usernameOne,String usernameTwo,int money) {
Connection con = null;
PreparedStatement pstmtOne = null;
PreparedStatement pstmtTwo = null;
ResultSet rs = null;
try {
con = DBCPDateSource.getConnection();
con.setAutoCommit(false); //开启事务 true自动提交 false手动提交
String sqlOne = "UPDATE user SET balance=balance-? WHERE username=?";
pstmtOne=con.prepareStatement(sqlOne);
pstmtOne.setInt(1, money);
pstmtOne.setString(2,usernameOne);
pstmtOne.executeUpdate();
//假设代码进行到此处时,程序中断,这里用一个隐式异常来模拟
//String s =null;
//获取s索引为2的内容
//s.charAt(2);
//此时你会发现数据库中,转钱的人钱已减少,但是收钱的人却没有收到
//如果要解决这种问题,就需要用到事务去避免 通过con.setAuToCommit()开启事务
String sqlTwo = "UPDATE user SET balance=balance+? WHERE username=?";
pstmtTwo=con.prepareStatement(sqlTwo);
pstmtTwo.setInt(1, money);
pstmtTwo.setString(2,usernameTwo);
pstmtTwo.executeUpdate();
con.commit();//提交事务 开启事务与提交事务之间的操作都为事务操作,如果期间有任何操作为执行成功,则期间所有的操作都无效
}catch(Exception e) {
e.printStackTrace();
}finally {
//因为此时我们需要关闭两个pstmt,传递两个pstmt参数,所以我们需要完善我们的工具类
DBCPDateSource.close(pstmtTwo, pstmtTwo, con);
}
}