自定义受检异常默认不触发回滚,需通过@dstransactional(rollbackfor=...)显式声明;应按图计算语义分层定义异常类型,并在aop失效时手动调用setrollbackonly()确保回滚。

自定义受检异常本身不会触发回滚,但通过显式配置可以精准控制分布式图计算中更新失败时的事务行为。关键不在于“能不能用受检异常”,而在于“如何让框架识别它并执行回滚”。
明确 @DSTransactional 对受检异常的默认态度
默认情况下,@DSTransactional(如 Seata、ShardingSphere 或自研分布式事务框架中的扩展注解)只对 RuntimeException 及其子类 和 Error 自动回滚。继承自 Exception 的自定义受检异常(如 GraphUpdateException)会被忽略,事务照常提交。
这是设计使然,并非缺陷——它把回滚决策权交还给开发者,避免误将业务可恢复异常(如网络重试后能成功的超时)当作致命错误。
用 rollbackFor 显式声明需回滚的受检异常
在方法上直接指定异常类型,是最常用也最清晰的方式:
- 定义受检异常:
public class GraphUpdateException extends Exception { ... } - 标注方法:
@DSTransactional(rollbackFor = GraphUpdateException.class)
- 抛出即生效:
throw new GraphUpdateException("顶点状态冲突,无法并发更新");
支持多个异常:rollbackFor = {GraphUpdateException.class, VersionConflictException.class}。注意:若异常是受检的,方法签名仍需 throws 声明,否则编译不通过。
结合分布式图场景做语义化分层
图计算更新失败原因多样,不是所有失败都该回滚全局事务。建议按语义分级定义异常:
-
必须回滚类:如
GraphConsistencyViolationException extends Exception(违反图结构约束,如环检测失败),配rollbackFor -
局部重试类:如
RemoteVertexTimeoutException extends Exception(远端节点响应超时),不配rollbackFor,由调用方捕获后重试或降级 -
跳过处理类:如
StaleEdgeSkipException extends RuntimeException(过期边自动忽略),用运行时异常+不回滚语义,避免污染事务边界
这种分层让回滚逻辑与图计算语义对齐,比统一 throw new Exception() 更可控。
补充手动回滚增强确定性
当异常发生在异步分支、回调或跨线程图遍历中,AOP 代理可能失效。此时应主动干预:
- 在 catch 块内调用:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); - 立即记录日志,说明“已标记回滚:图更新因 [原因] 失败”
- 确保后续代码不再修改数据库状态(如跳过写入、清空缓存)
该方式绕过异常类型判断,100% 触发回滚,适合高一致性要求的图更新场景(如金融关系图、权限依赖图)。











