本文目录导读:

我来为您提供一个完整的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中代码回滚的完整实现,从数据库事务到代码版本管理都覆盖到了。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播