package jdbc;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @author 小邱
* @version 0.0.1
* @description JdbcTransaction 事务操作
* @since 2021/9/28 19:08
* 要么相关的都操作,但凡有一个出错,相关的都要回滚到操作前的状态
* <p>
* JDBC程序中为了让多个 SQL 语句作为一个事务执行:
* 调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务
* 在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
* 在出现异常时,调用 rollback(); 方法回滚事务
* 若此时 Connection 没有被关闭,还可能被重复使用,则需要恢复其自动提交状态setAutoCommit(true)。
* 尤其是在使用数据库连接池技术时,执行close()方法前,建议恢复自动提交状态。
*/
public class JdbcTransaction {
//案例:张三给李四转账
@Test
public void test() {
Connection connection = null;
try {
//获取连接
connection = JdbcUtils.getConnection();
//设置不自动提交
connection.setAutoCommit(false);
String sql = "update account set balance = balance - 100 where name = ?";
update(connection, sql, "张三");
// 模拟网络异常
System.out.println(10 / 0);
sql = "update account set balance = balance + 100 where name = ?";
update(connection, sql, "李四");
//提交
connection.commit();
System.out.println("转账成功!");
//恢复自动提交
connection.setAutoCommit(true);
} catch (Exception throwables) {
System.out.println("转账失败!");
throwables.printStackTrace();
try {
//失败的回滚操作
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
} finally {
//关闭资源
JdbcUtils.close(connection, null);
}
}
public int update(Connection connection, String sql, Object... args) {
//预编译sql
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
//填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
//执行
return ps.executeUpdate();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
//关闭资源
JdbcUtils.close(null, ps);
}
return 0;
}
}