java jdbc 实现 tcc 模式的核心在于将数据库的原子操作拆解为 try、confirm 和 cancel 三个独立阶段,并通过本地事务控制每个阶段的执行与回滚。具体做法是定义一个包含这三个方法的接口,在业务调用时先开启事务执行 try 锁定资源,成功后提交事务;若后续 confirm 失败或需要补偿,则利用已保存的事务状态执行 cancel 释放资源并回滚。

TCC 接口如何定义与拆分
TCC 模式要求开发者手动实现业务逻辑的三个阶段,因此第一步是定义标准接口。通常使用注解驱动或模板方法模式来管理事务边界。以支付场景为例,Try 阶段负责检查余额并冻结资金,Confirm 阶段扣减冻结金额,Cancel 阶段解冻资金。这种拆分确保了每个阶段都是幂等的,且能独立通过 JDBC 提交或回滚。

public interface PaymentService {
@Tcc(confirmMethod = "confirm", cancelMethod = "cancel")
void tryPay(String orderId, BigDecimal amount);
void confirm(String orderId);
void cancel(String orderId);
}
上述代码展示了基于注解的简化定义。在实际 JDBC 实现中,@Tcc 注解处理器会拦截 tryPay 调用,自动管理事务生命周期。开发者只需关注具体的 SQL 逻辑,例如在 Try 中执行 UPDATE account SET frozen = frozen + ? WHERE id = ?,并确保该语句在事务内提交。
立即学习“Java免费学习笔记(深入)”;
掌握 ES6+ 特性,包括 async/await、解构、扩展运算符、箭头函数、Promise、模块、迭代器、生成器以及函数式编程模式,编写简洁高效的 Java
JDBC 事务如何配合 TCC 阶段
JDBC 连接对象默认处于自动提交模式,但在 TCC 模式下必须显式关闭自动提交以支持多阶段控制。在 Try 阶段,获取连接后设置 autoCommit(false),执行锁定逻辑后调用 commit()。如果 Try 成功但后续 Confirm 失败,系统需记录中间状态以便触发 Cancel。此时 Cancel 同样需要获取新的连接(或复用原连接上下文),再次设置非自动提交,执行逆向操作并提交。

// Try 阶段示例
Connection conn = dataSource.getConnection();
conn.setAutoCommit(false);
try {
// 冻结资金逻辑
preparedStatement.executeUpdate();
conn.commit(); // 提交 Try 结果
} catch (Exception e) {
conn.rollback(); // Try 失败直接回滚
throw e;
}
关键细节在于异常处理。JDBC 的 SQLException 必须被捕获并转换为 TCC 框架可识别的业务异常,否则框架无法判断是否进入 Confirm 或 Cancel 流程。同时,为防止网络抖动导致的状态不一致,建议引入本地消息表或日志表,记录每个阶段的执行状态,确保重试机制能准确找到对应的分支。
Confirm 失败时的 Cancel 触发机制
当 Confirm 阶段因超时或异常失败时,TCC 框架会启动补偿机制调用 Cancel 方法。在 JDBC 实现中,Cancel 的逻辑必须与 Try 严格对称。例如,Try 增加了冻结金额,Cancel 就必须减少相同的冻结金额并增加可用余额。由于 Cancel 可能多次被调用(重试),所有操作必须具备幂等性,即通过订单号或事务 ID 判断是否已经执行过补偿,避免重复释放资源。

















