如何实现事务回滚?

例如商品购买业务中,同时实现订单表支付状态的更改以及用户表账户余额的更改。如何保证其中一个更改操作失败时,另外一个操作自动撤销?

看到有一个@Before(Tx.class),但是不知如何使用,求指教。

评论区

杜福忠

2017-02-08 09:16

请打开手册第 : 5.5 声明式事务 章节

注意:MySql 数据库表必须设置为 InnoDB 引擎时才支持事务,MyISAM 并不支持事务。

最简单的方式:
在 Controller 的 Action 上面加@Before(Tx.class) ,
(ps:不能在其他类直接加 @Before(Tx.class), 如果需要使用, 具体使用方式参考 手册第4.6 Duang 、Enhancer 章节

如手册例:
@Before(Tx.class)
public void trans_demo() {// 这是 Controller 的一个 Action
//....
}

其他使用方式细读手册 :)
拦截器的配置方法见 Interceptor 有关章节 章节

杜福忠

2017-02-08 09:31

@杜福忠
ps:
@Before(Tx.class)
public void trans_demo() {// 这是 Controller 的一个 Action
//.... 这里面不能 try { } catch (){} 给吃掉, 如果业务需要,那就catch 捕获到以后需要再向上抛 throw,
}

比如写API的时候,就算异常了也要给调用者返回错误信息,不能是500吧,
我一般这样写:

// 这是 Controller 的一个 Action
//在前面加多个拦截器 参考手册第4.2 Interceptor 章节
@Before({renderJsonTxInterceptor.class, Tx.class})
public void trans_demo() {
//...
}


//这是 拦截器 renderJsonTxInterceptor的代码:
public class renderJsonTxInterceptor implements Interceptor {

@Override
public void intercept(Invocation inv) {
try {
//这里 测试就使用 System.out.println 了 生成是不能用的,会被打死
System.out.println("renderJsonTxInterceptor 进入");
inv.invoke();
System.out.println("renderJsonTxInterceptor 没有检查到异常");
} catch (Exception e) {
e.printStackTrace();
System.out.println("renderJsonTxInterceptor 捕获到异常,并放入错误码");
inv.getController().renderJson("{\"ret\":0}");//错误码自己定义,这里就不写了
}

}

}

暴风雪

2017-02-08 11:58

还有一个duang

JFinal

2017-02-08 12:05

@杜福忠 @暴风雪 感谢回复,社区建设需要大家的力量

事务支持在 jfinal 手册中有相关说明与示例

nbjgl

2017-02-08 16:05

手册自然是看了又看的啊,但是手册写得极其精简,对我这样的缺乏经验的小白来说 , 并不能够确定我的理解,在应用中是否真的正确。如果提出了问题,然后就让我看手册的话,其实我是看过了手册的。

nbjgl

2017-02-08 16:10

@杜福忠

在Order这个model中的dealOrder()方法前面加上这个@Before(Tx.class),如下:


@Before(Tx.class)
public void dealOrder(){
//....
}

然后在任意的位置可以这样调用:
enhance(Order.class).dealOrder() 。


这样调用是不是就对了?
我不需要自己写Tx.class了 对不对?

杜福忠

2017-02-08 16:36

enhance(Order.class).dealOrder() 这样写只能在Controller中使用, 因为在Controller中已经有这个方法了,所以您的Controller 就继承了!
Controller源码1237行以后, 这样写到:
public T enhance(Class targetClass) {
return (T)Enhancer.enhance(targetClass);
}


在任意的位置是这样调用的:
Enhancer.enhance(Order.class).dealOrder()


如手册第 4.6 Duang 、Enhancer 章的 例子:
public class TestMain{
public void main(String[] args) {
// 使用Duang.duang方法在任何地方对目标进行增强
OrderService service = Duang.duang(OrderService.class);
// 调用payment方法时将会触发拦截器
service.payment(…);
// 使用Enhancer.enhance方法在任何地方对目标进行增强
OrderService service = Enhancer.enhance(OrderService.class);
}
}

热门反馈

扫码入社