事务并没有回滚

public class RegisterService {
	
	public static final RegisterService me = new RegisterService();

	@Before(Tx.class)
	public boolean save(){
		Record account = new Record();		
		account.set("username", "test1");
		account.set("password", "test1");
		account.set("register_ip", "127.0.0.1");
		Db.use("1").save("t_account", account);
		Record bind = new Record();
		bind.set("account","test1");
		bind.set("openid","123456");
		Db.use("1").save("t_bind", bind);
		return true;
	}

}

第二张表我做了account字段做了唯一索引,第一次执行两张表另插入一条数据,第二次执行到bind表时候数据库会有一个异常,但是第一张表的数据并没有回滚,这是什么原因呢。

PS:项目使用了多个数据源这里的use("1")是存在的

评论区

ben0133

2018-05-22 17:00

经过测试,如果不是默认数据源,事务并不起使用。

JFinal

2018-05-22 22:02

@ben0133 如果不是默认数据源,对于 @Before(Tx.class) 拦截器方案来说,需要再添加一个配套的注解,例如:
@TxConfig("另一个数据源名,也即configName")
@Before(Tx.class)
public void method() {
...
}

对于 Db.tx 做事务来说,如果不是主数据源需要用下面的方式:
Db.use("另一个数据源名,也即configName").tx(...);

JFinal

2018-05-22 22:33

文档中补充了相关内容:
http://www.jfinal.com/doc/5-7

ben0133

2018-05-28 10:51

@JFinal 谢谢波总,因为数据源是根据访问参数会变化的,最终我是用下面代码解决的,jfinal提供的功能真是强大~
Db.use(configName).tx(new IAtom(){
@Override
public boolean run() throws SQLException {...}});

JFinal

2018-05-28 11:00

@ben0133 对,我个人是建议使用 Db.use(...).tx(...) 做事务,控制起来比较方便

现在很多项目是互联网项目,需要开启事务的地方并不多,大部分请求不需要开启事务,所以使用 Db.tx(...) 是很合适的

如果是一个内部的业务系统,并且大部分业务需要开启事务的话,使用拦截器开启事务,并配合一个全局拦截器 try catch 事务抛出的异常,并响应合适的 json/view 是最方便的

ben0133

2018-05-28 14:29

@JFinal 学习了~

JFinal

2018-05-28 15:35

@ben0133 在 java 8 下使用 Db.tx 可以使用 lambda 表达式,使用起来代码会更简洁:
public void test() {
final Ret ret = Ret.create();
Db.tx(() -> {
Db.update("update ta set f1 = ?", 123);
Db.update("update tb set f2 = ?", 456);
ret.set("key", 123); // 使用 ret 带回点数据
ret.set("msg", "xxxx"); // 使用 ret 带回多个数据
return true; // 返回 true 提交事务
});
}

上面的例子还演示了通过一个 final Ret 局部变量从 lambda 表达式中带回返回值的使用方法,返回多个值的需求也可以很方便地解决

ben0133

2018-05-30 17:56

@JFinal 学习了~

热门反馈

扫码入社