本文目录导读:

- 基于JDBC的简单回滚(最基础)
- Spring JDBC 模板的回滚(Spring框架)
- 基于Spring + MyBatis的完整案例
- 编程式事务管理(Spring)
- 事务传播行为示例
- 配置文件示例(application.yml)
- 数据库表结构
在Java中实现数据库回滚主要有几种方式,我将通过几个典型案例来展示。
基于JDBC的简单回滚(最基础)
import java.sql.*;
public class JDBCRollbackExample {
public static void main(String[] args) {
Connection conn = null;
try {
// 1. 获取数据库连接
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/test",
"root",
"password"
);
// 2. 关闭自动提交,开启事务
conn.setAutoCommit(false);
// 3. 执行多条SQL语句
Statement stmt = conn.createStatement();
// 模拟两个操作
stmt.executeUpdate("INSERT INTO users (name, age) VALUES ('张三', 25)");
// 故意制造一个错误
int result = 1 / 0; // 这里会抛出异常
stmt.executeUpdate("INSERT INTO users (name, age) VALUES ('李四', 30)");
// 4. 所有操作成功,提交事务
conn.commit();
System.out.println("事务提交成功!");
} catch (Exception e) {
// 5. 发生异常,回滚事务
if (conn != null) {
try {
conn.rollback();
System.out.println("事务已回滚!");
} catch (SQLException ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
} finally {
// 6. 关闭连接
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
Spring JDBC 模板的回滚(Spring框架)
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class UserService {
@Resource
private JdbcTemplate jdbcTemplate;
@Transactional(rollbackFor = Exception.class)
public void transferMoney(Long fromUserId, Long toUserId, Double amount) {
// 1. 扣款操作
String deductSql = "UPDATE accounts SET balance = balance - ? WHERE user_id = ?";
jdbcTemplate.update(deductSql, amount, fromUserId);
// 模拟一个异常
if (fromUserId.equals(toUserId)) {
throw new RuntimeException("不能转账给自己!");
}
// 2. 加款操作
String addSql = "UPDATE accounts SET balance = balance + ? WHERE user_id = ?";
jdbcTemplate.update(addSql, amount, toUserId);
// 如果以上任何一步出错,整个事务都会回滚
System.out.println("转账成功!");
}
}
基于Spring + MyBatis的完整案例
// 实体类
public class Account {
private Long id;
private String name;
private Double balance;
// getter和setter方法
}
// Mapper接口
@Mapper
public interface AccountMapper {
@Update("UPDATE account SET balance = balance - #{amount} WHERE id = #{id}")
int deductBalance(@Param("id") Long id, @Param("amount") Double amount);
@Update("UPDATE account SET balance = balance + #{amount} WHERE id = #{id}")
int addBalance(@Param("id") Long id, @Param("amount") Double amount);
}
// Service实现类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountMapper accountMapper;
@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void transfer(Long fromId, Long toId, Double amount) {
// 1. 校验余额是否充足
Account fromAccount = accountMapper.findById(fromId);
if (fromAccount.getBalance() < amount) {
throw new BusinessException("余额不足");
}
// 2. 扣款
int rows = accountMapper.deductBalance(fromId, amount);
if (rows == 0) {
throw new BusinessException("扣款失败");
}
// 模拟一个运行时异常
if (amount <= 0) {
throw new IllegalArgumentException("转账金额必须大于0");
}
// 3. 加款
rows = accountMapper.addBalance(toId, amount);
if (rows == 0) {
throw new BusinessException("加款失败");
}
}
}
// 自定义业务异常
public class BusinessException extends RuntimeException {
public BusinessException(String message) {
super(message);
}
}
编程式事务管理(Spring)
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
@Service
public class ProgrammaticTransactionService {
@Autowired
private PlatformTransactionManager transactionManager;
public void businessLogic() {
// 创建事务定义
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
// 开启事务
TransactionStatus status = transactionManager.getTransaction(def);
try {
// 业务逻辑
// ... 执行数据库操作
// 提交事务
transactionManager.commit(status);
System.out.println("事务提交成功");
} catch (Exception e) {
// 回滚事务
transactionManager.rollback(status);
System.out.println("事务回滚成功");
e.printStackTrace();
}
}
}
事务传播行为示例
@Service
public class TransactionPropagationExample {
@Autowired
private MethodA methodA;
@Service
public static class MethodA {
@Transactional
public void methodA() {
// 数据库操作1
insertData("A");
try {
methodB(); // 调用方法B
} catch (Exception e) {
// 即使方法B失败了,方法A的代码不会受影响(如果B使用REQUIRES_NEW)
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW) // 开启新事务
public void methodB() {
// 数据库操作2
insertData("B");
// 这里抛异常,只回滚方法B的事务
if (true) {
throw new RuntimeException("方法B的异常");
}
}
}
}
配置文件示例(application.yml)
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
# 事务管理器配置
jpa:
hibernate:
ddl-auto: create-drop
# 事务配置
transaction:
default-timeout: 30
# MyBatis配置
mybatis:
configuration:
map-underscore-to-camel-case: true
数据库表结构
-- 创建账户表
CREATE TABLE account (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
balance DECIMAL(10,2) NOT NULL DEFAULT 0
);
-- 创建用户表
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
age INT NOT NULL
);
-- 创建账户明细表
CREATE TABLE account_transaction_log (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
from_account_id BIGINT NOT NULL,
to_account_id BIGINT NOT NULL,
amount DECIMAL(10,2),
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
-
JDBC层面:通过
conn.setAutoCommit(false)关闭自动提交,手动控制commit()和rollback() -
Spring注解方式:
@Transactional是最常用的方式rollbackFor指定哪些异常触发回滚propagation设置事务传播行为
-
事务特性:
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
-
最佳实践:
- 尽量使用声明式事务(
@Transactional) - 异常要设置正确的
rollbackFor - 避免长事务
- 注意事务的隔离级别
- 尽量使用声明式事务(
这个案例涵盖了从基础的JDBC到Spring框架的各种回滚实现方式,可以根据项目需求选择合适的方式。
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播