本文目录导读:

我来为您提供一个完整的Java代码回滚案例,包含数据库事务回滚和代码版本回滚两个层面。
数据库事务回滚案例
场景:银行转账系统
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class BankTransferService {
private static final String DB_URL = "jdbc:mysql://localhost:3306/bank";
private static final String USER = "root";
private static final String PASSWORD = "password";
/**
* 转账操作(带事务回滚)
* @param fromAccount 转出账户
* @param toAccount 转入账户
* @param amount 转账金额
*/
public void transfer(String fromAccount, String toAccount, double amount) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
// 1. 获取数据库连接
conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);
// 2. 关闭自动提交,开启事务
conn.setAutoCommit(false);
// 3. 扣款操作
String deductSql = "UPDATE accounts SET balance = balance - ? WHERE account_no = ?";
pstmt = conn.prepareStatement(deductSql);
pstmt.setDouble(1, amount);
pstmt.setString(2, fromAccount);
int deductResult = pstmt.executeUpdate();
if (deductResult == 0) {
throw new SQLException("转出账户不存在");
}
// 4. 检查余额是否足够
String checkSql = "SELECT balance FROM accounts WHERE account_no = ?";
pstmt = conn.prepareStatement(checkSql);
pstmt.setString(1, fromAccount);
var rs = pstmt.executeQuery();
if (rs.next() && rs.getDouble("balance") < 0) {
throw new SQLException("余额不足");
}
// 5. 入账操作
String creditSql = "UPDATE accounts SET balance = balance + ? WHERE account_no = ?";
pstmt = conn.prepareStatement(creditSql);
pstmt.setDouble(1, amount);
pstmt.setString(2, toAccount);
int creditResult = pstmt.executeUpdate();
if (creditResult == 0) {
throw new SQLException("转入账户不存在");
}
// 6. 记录交易日志
String insertLogSql = "INSERT INTO transaction_log (from_account, to_account, amount, status) VALUES (?, ?, ?, ?)";
pstmt = conn.prepareStatement(insertLogSql);
pstmt.setString(1, fromAccount);
pstmt.setString(2, toAccount);
pstmt.setDouble(3, amount);
pstmt.setString(4, "SUCCESS");
pstmt.executeUpdate();
// 7. 事务提交
conn.commit();
System.out.println("转账成功!");
} catch (SQLException e) {
// 8. 发生异常,执行回滚
if (conn != null) {
try {
conn.rollback();
System.out.println("转账失败,已回滚事务!");
} catch (SQLException ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
} finally {
// 9. 释放资源
try {
if (pstmt != null) pstmt.close();
if (conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
使用Spring @Transactional注解的事务回滚
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class OrderService {
@Transactional(rollbackFor = RuntimeException.class)
public void createOrder(Order order) {
try {
// 1. 创建订单
orderDao.insert(order);
// 2. 扣减库存
int result = productDao.deductStock(order.getProductId(), order.getQuantity());
if (result == 0) {
throw new RuntimeException("库存不足");
}
// 3. 其他业务操作
userDao.updateUserScore(order.getUserId(), order.getTotalAmount() * 10);
} catch (Exception e) {
// Spring会自动回滚事务
throw new RuntimeException("创建订单失败:" + e.getMessage());
}
}
/**
* 手动控制回滚
*/
@Transactional(rollbackFor = Exception.class)
public void manualRollback(Order order) {
// 使用TransactionAspectSupport手动回滚
try {
// 业务逻辑
processOrder(order);
} catch (Exception e) {
// 主动触发回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw e;
}
}
}
代码版本回滚工具类
简单的代码版本管理器
import java.util.Stack;
import java.util.HashMap;
import java.util.Map;
public class CodeVersionManager {
// 存储代码快照
private static Map<String, Stack<CodeSnapshot>> versionStacks = new HashMap<>();
// 代码快照类
private static class CodeSnapshot {
private String version;
private String codeContent;
private long timestamp;
public CodeSnapshot(String version, String codeContent) {
this.version = version;
this.codeContent = codeContent;
this.timestamp = System.currentTimeMillis();
}
public String getVersion() {
return version;
}
public String getCodeContent() {
return codeContent;
}
public long getTimestamp() {
return timestamp;
}
}
/**
* 保存代码快照
*/
public static void saveSnapshot(String module, String filePath, String codeContent) {
String key = module + ":" + filePath;
versionStacks.computeIfAbsent(key, k -> new Stack<>());
String version = "v" + (versionStacks.get(key).size() + 1);
versionStacks.get(key).push(new CodeSnapshot(version, codeContent));
System.out.println("已保存快照,版本号:" + version);
}
/**
* 回滚到上一个版本
*/
public static String rollback(String module, String filePath) {
String key = module + ":" + filePath;
Stack<CodeSnapshot> stack = versionStacks.get(key);
if (stack == null || stack.isEmpty()) {
return null;
}
CodeSnapshot snapshot = stack.pop();
System.out.println("回滚到版本:" + snapshot.getVersion() + ",时间:" +
new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date(snapshot.getTimestamp())));
return snapshot.getCodeContent();
}
/**
* 查看历史版本
*/
public static void showHistory(String module, String filePath) {
String key = module + ":" + filePath;
Stack<CodeSnapshot> stack = versionStacks.get(key);
if (stack != null && !stack.isEmpty()) {
System.out.println("历史版本列表:");
for (CodeSnapshot snapshot : stack) {
System.out.println("- " + snapshot.getVersion());
}
} else {
System.out.println("该文件没有历史版本");
}
}
}
使用示例
public class VersionControlExample {
public static void main(String[] args) {
// 模拟代码文件的版本控制
String module = "user-service";
String filePath = "UserService.java";
// 保存不同版本的代码
CodeVersionManager.saveSnapshot(module, filePath,
"class UserService {\n public void createUser() {\n // v1 实现\n }\n}");
CodeVersionManager.saveSnapshot(module, filePath,
"class UserService {\n public void createUser() {\n // v2 实现(包含bug)\n }\n}");
CodeVersionManager.saveSnapshot(module, filePath,
"class UserService {\n public void createUser() {\n // v3 实现\n }\n}");
// 查看版本历史
CodeVersionManager.showHistory(module, filePath);
// 发现v3有bug,回滚到v2
String rolledBackCode = CodeVersionManager.rollback(module, filePath);
System.out.println("回滚后的代码:\n" + rolledBackCode);
// 再回滚到v1
String rollbackToV1 = CodeVersionManager.rollback(module, filePath);
System.out.println("再次回滚后的代码:\n" + rollbackToV1);
}
}
Spring Boot 事务管理完整案例
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private AccountRepository accountRepository;
/**
* 下单并支付(包含完整事务)
*/
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED,
rollbackFor = Exception.class
)
public String placeOrderAndPay(Order order, PaymentInfo paymentInfo) {
try {
// 1. 验证用户和商品
validateOrder(order);
// 2. 创建订单(状态:待支付)
Order savedOrder = orderRepository.save(order);
// 3. 扣减库存
deductStock(order.getProductId(), order.getQuantity());
// 4. 执行支付
boolean paymentResult = processPayment(savedOrder, paymentInfo);
if (!paymentResult) {
throw new PaymentException("支付失败");
}
// 5. 更新订单状态为已支付
savedOrder.setStatus("PAID");
orderRepository.save(savedOrder);
// 6. 记录操作日志
logOrder(savedOrder);
// 返回订单号
return savedOrder.getOrderNo();
} catch (PaymentException e) {
// 当发生特定异常时回滚事务
throw new TransactionException("订单处理失败,事务已回滚", e);
} catch (Exception e) {
// 其他异常也会触发回滚
throw new TransactionException("系统异常,事务已回滚", e);
}
}
/**
* 部分提交示例
*/
@Transactional
public void partialCommitExample() {
// REQUIRED: 会加入到当前事务
helperMethod1();
// REQUIRES_NEW: 会开启新事务
helperMethod2();
// NESTED: 如果有事务就嵌套,否则开启新事务
helperMethod3();
}
private void validateOrder(Order order) {
// 验证逻辑
}
private void deductStock(Long productId, int quantity) {
// 扣减库存逻辑
}
private boolean processPayment(Order order, PaymentInfo paymentInfo) {
// 支付处理逻辑
return true;
}
private void logOrder(Order order) {
// 日志记录
}
// 自定义异常类
static class PaymentException extends RuntimeException {
public PaymentException(String message) {
super(message);
}
}
static class TransactionException extends RuntimeException {
public TransactionException(String message, Throwable cause) {
super(message, cause);
}
}
}
使用AOP实现自定义回滚逻辑
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
@Aspect
@Component
public class TransactionAdvice {
/**
* 自定义事务管理切面
*/
@Around("@annotation(customTransaction)")
public Object handleTransaction(ProceedingJoinPoint joinPoint, CustomTransaction customTransaction)
throws Throwable {
Object result = null;
boolean isSuccessful = true;
try {
// 前置处理
System.out.println("开启事务");
// 执行目标方法
result = joinPoint.proceed();
// 后置处理(成功)
System.out.println("事务提交成功");
} catch (Exception e) {
isSuccessful = false;
// 回滚处理
if (customTransaction.rollbackOnException()) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
System.out.println("事务回滚");
}
throw e;
} finally {
// 无论成功失败都会执行
System.out.println("是否成功:" + isSuccessful);
}
return result;
}
// 自定义注解
@interface CustomTransaction {
boolean rollbackOnException() default true;
}
}
最佳实践建议
-
事务回滚:
- 使用Spring的声明式事务(@Transactional)而非编程式事务
- 合理设置rollbackFor属性
- 避免事务方法内try-catch吞掉异常
-
代码回滚:
- 使用Git等版本控制工具
- 保持提交的原子性
- 定期创建tag或release
-
监控与日志:
- 记录事务边界日志
- 实现失败自动回滚机制
- 设置合理的超时时间
-
性能优化:
- 事务范围要尽量小
- 合理使用读写分离
- 避免长事务
这个案例展示了Java中代码回滚的完整实现,从数据库事务到代码版本管理都覆盖到了。