在进行修改测试的时候报了个大长错。这里就不全贴在这里了因为太长了,我提取了所有主要信息供参考:

1. 顶层调用异常:

org.apache.dubbo.rpc.RpcException: Failed to invoke the method updateAdminRole in the service com.moriha.common.service.AdminService. Tried 3 times of the providers [192.168.126.1:20882] (1/1)
from the registry 192.168.0.99:8848 on the consumer 192.168.126.1 using the dubbo version 3.2.4.
Last error is: Failed to invoke remote method: updateAdminRole

2. 中间包装异常

Caused by: org.apache.dubbo.remoting.RemotingException: java.io.IOException: org.apache.dubbo.common.serialize.SerializationException: com.alibaba.fastjson2.JSONException: autotype not support : org.springframework.jdbc.UncategorizedSQLException

3. 根因异常

Caused by: com.alibaba.fastjson2.JSONException: autotype not support : org.springframework.jdbc.UncategorizedSQLException

报错解释:

  • RpcException: Failed to invoke the method updateAdminRole Dubbo 消费者调用远程接口updateAdminRole方法失败,已重试 3 次服务提供者依旧失败。
  • RemotingException Dubbo 网络通信层出现异常,服务端向客户端回传数据时 IO 异常。
  • SerializationException Dubbo 序列化环节出错,使用 FastJson2 序列化数据失败。
  • fastjson2.JSONException: autotype not support : UncategorizedSQLException FastJson2 默认关闭自动类型解析(autotype)安全机制,无法对 Spring 数据库通用异常UncategorizedSQLException进行序列化、反序列化;服务端数据库报错后,异常实例无法序列化传回调用方,直接打断 RPC 调用。

这个的意思总结一下就是:【提供者端(shopping_admin_service)执行 SQL 时抛出了 UncategorizedSQLException,然后 Dubbo 尝试用 fastjson2 序列化这个异常对象时失败了。】

核心字段: UncategorizedSQLException 是 Spring 对 MyBatis、JDBC 所有无法归类的数据库底层异常的统一封装类,只要出现这个异常类名,就代表服务端 SQL 执行、数据库操作直接报错了

层级关系 数据库 SQL 异常→抛出 UncategorizedSQLException→FastJson2 无法序列化该异常→触发 SerializationException 序列化异常→产生 RemotingException 网络 IO 返回异常→最终外层包装 RpcException 远程调用失败。

所以可以想到产生的原因大概是:

  1. 业务方法内部 SQL 执行出错,数据库抛出异常,产生 UncategorizedSQLException 异常对象;
  2. 其他该异常连锁传导后的衍生异常。
  • Dubbo 选用 FastJson2 做序列化,未开启 autotype 白名单,复杂异常类无法序列化传输;
  • 服务端异常序列化失败,网络响应数据构造失败,触发 Dubbo 底层 RemotingException 通信异常;
  • 远程接口多次重试依旧无法正常返回结果,Dubbo 外层包装为 RpcException 调用失败异常。

根因是 SQL 参数错误抛出数据库异常,才触发序列化失败

经过我的排查发现:

我写的 addRoleToAdmin 方法的参数是 Long[] rids(数组),但 XML 中直接用了 #{rid}

XML 未使用 foreach 遍历直接取值,SQL 参数绑定错误触发数据库异常,进而连锁引发 2、3、4 号上层框架异常。

我没有实现数组遍历导致了这个报错。为了更直观好理解,我把问题代码粘在这里:
 

// ... existing code ...
    //给管理员添加角色    (我写成了Long[] rids 而非现在这样)
    void addRoleToAdmin(@Param("aid") Long aid, @Param("rid") Long rid);
}
// ... existing code ...
    @Override
    public void updateAdminRole(Long aid, Long[] rids) {
        // 删除管理员所有角色
        adminMapper.deleteAdminAllRole(aid);
        // 重新添加管理员角色
        for (Long rid : rids) {    
            // 因为刚才的失误,这里允许写成 new Long[] rids
            adminMapper.addRoleToAdmin(aid, rid);
        }
    }
// ... existing code ...

改动说明

  • AdminMapper.javaLong[] ridsLong rid,改为接收单个角色 ID
  • AdminServiceImpl.javanew Long[]{rid}rid,循环中直接传单个值

这样 XML 中的 #{rid} 就能正确绑定到单个 Long 值了,SQL 不再报错。

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐