在学习和使用jfinal 框架,写了一个类TestService 想做中间层。里面有两个 model test 和test2 。 在TestService中分别new 出两个model 然后做数据库插入操作,在test 插入操作之后抛出sqlException("出错") 在类中用的是@Brfore(Tx.class)的注解。 不知为何不会回滚
代码如下:
package com.woniu157.sys.test;
import java.sql.Connection;
import com.jfinal.aop.Before;
import com.jfinal.plugin.activerecord.DbKit;
import com.jfinal.plugin.activerecord.tx.Tx;
import com.woniu157.sys.user.User;
public class TestService {
@Before(Tx.class)
public void testTran() throws Exception{
//DbKit.setThreadLocalConnection(null);
Test t=new Test();
Test2 t2=new Test2();
t2.getsomeThine();
t.getsomeThine();
}
}
package com.woniu157.sys.test;
import java.sql.SQLException;
import com.jfinal.plugin.activerecord.Model;
public class Test2 extends Model<Test2> {
public static final Test2 dao=new Test2();
public void getsomeThine() throws SQLException{
dao.set("id", 1);
dao.set("name", "zm33m");
dao.save();
throw new SQLException("");
}
}
package com.woniu157.sys.test;
import com.jfinal.plugin.activerecord.Model;
public class Test extends Model<Test> {
public static final Test dao=new Test();
public void getsomeThine(){
dao.set("id", 1);
dao.set("name", "zmm");
dao.save();
}
}
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
"
建议仔细看一下 jfinal 手册,一共才30 多页,而且大部分是代码示例。楼主碰到的问题在jfinal 手册第25页有如下说明:
<img src=""http://static.oschina.net/uploads/space/2014/0113/181020_reqX_201137.png"" alt="""" />
建议仔细看一下 jfinal 手册,一共才30 多页,而且大部分是代码示例。楼主碰到的问题在jfinal 手册第25页有如下说明:
我还有个三个问题,还望赐教
问题1 :即使我把上面保存方法换成new Model.Set(...),在最后抛出错误 ,数据库依然能够保存成功。
@Before(Tx.class) public void doSomeThine(){ Test t=new Test(); t.set("id",1111); t.set("name","zhoumaomao"); t.save(); Test2 t=new Test2(); t2.set("id",33333); t2.set("name","zmm"); t2.save(); throw new sqlException("出错啦..."); }问题二:如果我改用db.tx(obj instance IAtom) 就能够原子执行,我看您的源码都是从线程中获取conn 。不知为何
问题三:我看您的@Before(Tx.class)都写在Action 层,那这样 假设我手动抛出异常,在Action层如果手动捕捉,那Tx 就捕捉不到,如果再往上抛出,那则遇到“系统错误”请问这种情况该怎么处理?
建议仔细看一下 jfinal 手册,一共才30 多页,而且大部分是代码示例。楼主碰到的问题在jfinal 手册第25页有如下说明:
我还有个三个问题,还望赐教
问题1 :即使我把上面保存方法换成new Model.Set(...),在最后抛出错误 ,数据库依然能够保存成功。
@Before(Tx.class) public void doSomeThine(){ Test t=new Test(); t.set("id",1111); t.set("name","zhoumaomao"); t.save(); Test2 t=new Test2(); t2.set("id",33333); t2.set("name","zmm"); t2.save(); throw new sqlException("出错啦..."); }问题二:如果我改用db.tx(obj instance IAtom) 就能够原子执行,我看您的源码都是从线程中获取conn 。不知为何
问题三:我看您的@Before(Tx.class)都写在Action 层,那这样 假设我手动抛出异常,在Action层如果手动捕捉,那Tx 就捕捉不到,如果再往上抛出,那则遇到“系统错误”请问这种情况该怎么处理?
}
的确,事务的回滚在拦截器那边,如果action层捕获异常,则事务无法回滚了..在该怎么解决?
建议仔细看一下 jfinal 手册,一共才30 多页,而且大部分是代码示例。楼主碰到的问题在jfinal 手册第25页有如下说明:
我还有个三个问题,还望赐教
问题1 :即使我把上面保存方法换成new Model.Set(...),在最后抛出错误 ,数据库依然能够保存成功。
@Before(Tx.class) public void doSomeThine(){ Test t=new Test(); t.set("id",1111); t.set("name","zhoumaomao"); t.save(); Test2 t=new Test2(); t2.set("id",33333); t2.set("name","zmm"); t2.save(); throw new sqlException("出错啦..."); }问题二:如果我改用db.tx(obj instance IAtom) 就能够原子执行,我看您的源码都是从线程中获取conn 。不知为何
问题三:我看您的@Before(Tx.class)都写在Action 层,那这样 假设我手动抛出异常,在Action层如果手动捕捉,那Tx 就捕捉不到,如果再往上抛出,那则遇到“系统错误”请问这种情况该怎么处理?
}
的确,事务的回滚在拦截器那边,如果action层捕获异常,则事务无法回滚了..在该怎么解决?
对于 web 项目来说通常让异常抛出,跳到 500 页面即可,如果还干预更多,可以 Tx 拦截器前面再设置个拦截器在更外层捕获到异常再做后续处理。之所以是异常理应很少出现,意外出现跳去 error 500 并做了日志,已经比较合理
另外还可以使用boolean result = Db.tx(...) 方法来得到事务是否成功的结果,也可以在外层捕获异常再继续做处理
建议仔细看一下 jfinal 手册,一共才30 多页,而且大部分是代码示例。楼主碰到的问题在jfinal 手册第25页有如下说明:
我还有个三个问题,还望赐教
问题1 :即使我把上面保存方法换成new Model.Set(...),在最后抛出错误 ,数据库依然能够保存成功。
@Before(Tx.class) public void doSomeThine(){ Test t=new Test(); t.set("id",1111); t.set("name","zhoumaomao"); t.save(); Test2 t=new Test2(); t2.set("id",33333); t2.set("name","zmm"); t2.save(); throw new sqlException("出错啦..."); }问题二:如果我改用db.tx(obj instance IAtom) 就能够原子执行,我看您的源码都是从线程中获取conn 。不知为何
问题三:我看您的@Before(Tx.class)都写在Action 层,那这样 假设我手动抛出异常,在Action层如果手动捕捉,那Tx 就捕捉不到,如果再往上抛出,那则遇到“系统错误”请问这种情况该怎么处理?
问题一:Tx 拦截器只要捕获到异常就一定会回滚事务,检查一下数据库引是否为 innodb(对于mysql来说),myisam不支持事务
问题二:从 ThreadLocal 中获取 conn 是为了实现事务控制,当ThreadLocal中能取到conn,证明是在事务之中,证明本线之前有数据库操作并获取过 conn,那么本线程当前的数据库操作就不必再从 DataSource中获取 conn,使用本线程已有 conn , 好让多次数据库操作使用同一个conn,从而可以实现统一 commit()
问题三:在 Tx 拦截器再放置一个拦截器再次捕获 Tx 的往上抛出的异常。也可以用一个独立的拦截器使用 Db.tx(...) 来包裹 ai.invoke(),实现事务,并在 Db.tx(...)捕获异常