要求:
如上图所示,AA用户给BB用户转账100,也就是说AA用户的账户余额变为900的时候需要BB的账户余额变为1100,这是需要同时处理的事务,两个事务要么同时完成,要么同时失败。这需要使用事务的处理。
数据一旦提交,就不可回滚,下面考虑在什么情况下会自动提交:
哪些操作会导致数据的自动提交?
1、 >DDL操作一执行,都会自动提交。
>set autoc ommit =false对DDL操作失效
2、>DML默认情况下,一旦执行,就会自动提交。
>我们可以通过set autocommit = false的方式取消DML操作的 自动提交。
3、>默认在关闭连接时,会自动的提交数据
通过上面可以看到,最后两点都会导致事务的自动提交,所以代码要顾及两个方面,一个是DML默认情况下的事务自动提交要关闭(conn.setAutoCommit(false)),还有一个是当连接关闭时的自动关闭的避免(update中JDBCUtils.closeResource(null,ps))。所以这里需要将之前的增删改update函数进行一些修改,将连接的关闭交给事务处理。
当转账出现异常时,要实现回滚操作,代码在异常里实现,捕捉到异常之后,执行回滚的操作。
代码如下:
package com.atguigu1.transaction;
import com.atguigu1.util.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TransactionTest {
public static void main(String[] args) {
Connection conn= null;
try {
conn = JDBCUtils.getConnection();
System.out.println(conn.getAutoCommit());
conn.setAutoCommit(false);
//AA用户给BB用户转账100
String spl1="update user_table set balance=balance-100 where user=?";
update(conn,spl1,"AA");
System.out.println(10/0);//用于模拟异常操作
String spl2="update user_table set balance=balance+100 where user=?";
update(conn,spl2,"BB");
System.out.println("转账成功");
conn.commit();
} catch (Exception e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}finally {
JDBCUtils.closeResource(conn,null);
}
}
public static int update(Connection conn,String sql,Object...args){
PreparedStatement ps= null;
try {
ps = conn.prepareStatement(sql);
for (int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
conn.setAutoCommit(true);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
JDBCUtils.closeResource(null,ps);
}
return 0;
}
}