- 之前一直在想一个问题:直接回滚和回滚到标记的地方有什么不一样!自己也测试了很多次,突然就想通了!还是很开心的!希望能帮助一些正在努力的人!
- 题目;zs和lisi银行转账的小测试!
- 思路:如果zs已经转了钱给李四卡里的钱已经减了,然后在中途出了点事故,李四没有收到钱,这钱要不回到张三的卡中要不再次转到李四的卡中。
- 这里使用了JDBCUtil的工具类:在之前的的博客中有就不在这里复制了!
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Connection conn = JDBCUtilDemo03.getConnection();
Statement stmt = conn.createStatement();
//设置zs转ls1000元钱,
String sql = "update t_act set t_money=t_money-1000 where t_name='zs'";
String sql1 = "update t_act set t_money=t_money+1000 where t_name='ls'";
//false为手动控制事务的操作不会自动提交
conn.setAutoCommit(false);//开启事务
Savepoint sp=null;// 设置回滚点事务标记点
try {
int rs1 = stmt.executeUpdate(sql);
if (rs1 > 0) {
System.out.println("李四转账成功!");
}
//设置回滚标点
sp=conn.setSavepoint();
//设置错误点
int i=1/0;
int rs2 = stmt.executeUpdate(sql1);
if (rs2 > 0) {
System.out.println("zs收账成功!");
}
} catch (Exception e) {
System.out.println("转账失败!再次请求收账!");
//测试一:转账失败后回滚到设置的回滚标记点
conn.rollback();
//测试二:不回滚到标记点
conn.rollback(sp);
int rs2 = stmt.executeUpdate(sql1);
if (rs2 > 0) {
System.out.println("zs收账成功!");
}
} finally {
//最后提交事务
conn.commit();
System.out.println("这里的finally");
String sql3 = "select * from t_act";
ResultSet rs = stmt.executeQuery(sql3);
while (rs.next()) {
System.out.println(rs.getObject(1) + "\t" + rs.getObject(2));
}
先是测试一:不回滚到标记点中
李四转账成功!
转账失败!再次请求收账!
zs收账成功!
这里的finally
zs 6000
ls 7000
- 可以看到李四转账成功却没扣款成功,这是因为:rollback()-回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
- 撤回回后在执行回滚后的代码,这样就实现了zs转账失败但是ls收账成功的效果了,这样银行就亏大发了1
- 测试二:conn.rollback(sp);
李四转账成功!
转账失败!再次请求收账!
zs收账成功!
这里的finally
zs 5000
ls 7000
- 这样就会回滚到所标记的代码之下,之前的zs转账成功就不会撤销了,这样就实现了回滚和回滚在标记点的区别了!