事务处理Before(Tx.class)诡异的问题

版本是5.1.1,在Config onStart中已配置:

Tx.setTxFun((inv, conn) -> {
   inv.invoke();
   Object returnValue = inv.getReturnValue();
   if (returnValue instanceof Ret) {
      Ret ret = (Ret) returnValue;
      if (ret.isFail()) {
	conn.rollback();
	return;
      }
      conn.commit();
   }
});

在Service中这样写:

@Before(Tx.class)
public Ret save(CLA2 o, KB02 kb02) throws Exception {
    //业务代码
    return Ret.ok();
}

在工开发电脑上没有出现问题,更新到服务器(linux/windows service)上,有些服务器也没有问题,但有些电脑又出现500错误,跟踪发现,Controller中使用到了这个Servcice,并且是使用@Inject注入,无法访问到这Controller中的方法,直接500.

如果修改为这样:

public Ret save(CLA2 o, KB02 kb02) throws Exception {
   final Ret ret = Ret.create();
   Db.tx(() -> {
     try {
        //业务代码
        ret.ok();
        return true;
     }catch (Exception e) {
        ret.fail();
	return false;
    }
   
    return ret;
}

这样写又没有问题了,适用所有服务器,都不会报500.

请问大家有没有遇到过这种情况?

评论区

JFinal

2024-04-20 14:50

没有异常信息,不好判断,根据异常信息仔细判断一下

此外,建议升级到最高版本

北流家园网

2024-04-20 16:01

@JFinal 文档中提到:Tx 事务拦截器在捕捉到异常后回滚事务,会再次抛向外抛出异常,所以在使用 Tx 拦截器来做事务处理时,通常需要再额外添加一个 ExceptionInterceptor,放在 Tx 拦截器之前去再次捕捉到 Tx 所抛出的异常,然后在这里做 renderJson/render 之类的动作向客户端展示不同的数据与页面。如果不添加这样的机制,会展示一个统一默认的 500 error 页面,无法满足所有需求。

但也没有具体说明是什么原因。
我项目里有很多地方都是使用Before(Tx.class)的,我得改好多哪。
使用到了Before(Tx.class),还需要配置拦截器吗?

JFinal

2024-04-20 20:32

配置一个全局拦截器,统一处理异常,这个异常也不一定是事务内抛出的异常

总归要这么一个全局拦截器进行兜底

doubuxingle

2024-06-19 17:44

你修改后在tx内部try之后没问题,说明就是你的有些业务代码抛异常了,然后你又没有进行兜底捕获处理,想要方便点你就直接在Tx.setTxFun中对inv.invoke()进行try然后在对应的catch里rollback即可。

热门反馈

扫码入社