什么是事务处理原则下的转账操作实现,最直白的解释就是我转出的钱对方需要收到,事件是针对整体的,不能我的钱转出,对方不仅没有收到,我的钱还扣除了,这就是不符合事物逻辑的。所以如果我的钱转出,对方没有收到,需要把我转出的钱返还给我,这就是最经典的事务处理逻辑
目录
事务处理的原则
保证所有事物都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事物中执行多个操作时,要么所有的事物都被提交(commit),那么这些修改就永久地保存下来,要么数据库管理系统将放弃所做的所有修改,整个事物回滚(rollback)到最初状态
导致数据不可回滚的操作
DDL(数据定义语言,主要是进行定义 / 改变数据表的结构、数据类型、表之间的链接等操作,常用的语句关键字有 CREATE、DROP、ALTER 等)操作一旦执行,都会自动提交
set autocommit = false 对 DDL 操作失效
DML(数据操纵语言,主要是对数据进行增加、删除、修改操作,常用的语句关键字有 INSERT、UPDATE、DELETE 等)默认情况下,一旦执行,就会自动提交
set autocommit = false 的方式取消 DML 操作的自动提交
默认在关闭连接(比如退出集成开发环境)时,会自动提交数据
代码实现事件转账
本文使用的数据表如下
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;
import org.junit.Test;
public class TratesactionTest {
@Test
public void Tx() {
Connection conn = null;
try {
//读取文件中的信息
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
//将用户名和密码封装在Properties中
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
//加载驱动
Class.forName(driverClass);
//获取连接
conn = (Connection) DriverManager.getConnection(url, user, password);
//取消数据库的自动提交
conn.setAutoCommit(false);
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");
System.out.println("转账成功");
//提交数据
conn.commit();
} catch (Exception e) {
e.printStackTrace();
//回滚数据
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
public int update(Connection conn,String sql,Object...args) {
PreparedStatement ps = null;
try {
//1.预编译sql语句,返回PreparedStatement实例
ps = conn.prepareStatement(sql);
//2.填充占位符
for (int i = 0;i < args.length;i++) {
ps.setObject(i + 1, args[i]);
}
//3.执行
return ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}try {
//修改其为自动提交数据,主要针对于数据库连接池的使用
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
}
return 0;
}
}
执行代码,实现转账成功