以下是说明文档里 声明式事务的源码:
@Before(Tx.class) public void trans_demo() { // 获取转账金额 Integer transAmount = getParaToInt("transAmount"); // 获取转出账户id Integer fromAccountId = getParaToInt("fromAccountId"); // 获取转入账户id Integer toAccountId = getParaToInt("toAccountId"); // 转出操作 Db.update("update account set cash = cash - ? where id = ?", transAmount, fromAccountId); // 转入操作 Db.update("update account set cash = cash + ? where id = ?", transAmount, toAccountId); }
以下是我的部分源码:
问题:直接用model的save和update是不是无法支持事务?我现在碰到的问题就是保存和更新的时候 ,出错后前面执行的数据都没有回滚。如果这样不行的话 ,该怎么通过model的方法去控制事务?
public class PayController extends Controller { PayService payService = Enhancer.enhance(PayService.class,Tx.class); public void addPay() { Pay pay = getModel(Pay.class, "pay"); pay.setIndate(new Date()); boolean flag = payService.savePay(pay); if (flag) payManage(); } }
public class PayService { // 分发资金 @Before(Tx.class) public boolean savePay(Pay pay) { boolean flag = false; try { if (pay == null) { return flag; } flag = pay.save(); if (flag) { // 更新预约状态为已缴费 Appoint appoint = Appoint.dao.findById(pay.getAid()); appoint.setStatus(2);// 已缴费 flag = appoint.update(); } // 生成一级机构资金记录 Integer agid = pay.getAgid(); if (flag && agid != null) { Assetsin assetsin = new Assetsin(); // 查询机构详细信息 Agency agency = Agency.dao.findById(agid); if (agency != null) { // 机构id assetsin.setAid(agid); // 预约id assetsin.setApptid(pay.getAid()); // 机构名称 assetsin.setAname(pay.getAgname()); // 机构编号 assetsin.setAcode(pay.getAcode()); // 客户id assetsin.setCid(pay.getCid()); // 客户姓名 assetsin.setCname(pay.getCname()); // 发放标识 默认未发放 assetsin.setFlag(false); // 资金总额 Double sum = pay.getSum(); assetsin.setSum(sum); // 查询 List<Rate> rateList = Rate.dao.find("select rate,level from rate"); double rate1 = 0D; double rate2 = 0D; for (Rate rate : rateList) { if (rate.getLevel() == 1) rate1 = rate.getRate(); if (rate.getLevel() == 2) rate2 = rate.getRate(); } // 比例 assetsin.setRate(rate1); Double amount = sum * rate1 / 100; assetsin.setAmount(amount); flag = assetsin.save(); if (flag) { // 给上级机构记录资金明细 Integer parentid = agency.getParentid(); if (parentid != null) { agency = Agency.dao.findById(parentid); if (agency != null) { assetsin.setId(null); assetsin.setAid(parentid); assetsin.setAname(agency.getName()); assetsin.setAcode(agency.getCode()); assetsin.setRate(rate2); amount = sum * rate2 / 100; assetsin.setAmount(amount); flag = assetsin.save(); } } } } } return flag; } catch (Exception e) { e.printStackTrace(); } return flag; } }
新人学习jfinal中,希望大神不吝赐教,在此感谢!
最后感谢詹总提供这么好的框架和平台!
此外,还要注意 mysql 只有 innodb 引擎才支持事务,myisam 天然不支持事务,还要注意事务级别是否匹配当前的数据库操作,如果是 jfinal 3.0 版本,默认级别比较高,一般不需要调整
最后,上面的代码中,既然 savePay 中已经使用了 @Before 声明了事务,那么在 enhance 时就不需要添加 Tx.class 这个参数了
最后的最后,个人一般建议直接使用 Db.tx(...) 的方式支持事务,控制起来更加方便,例如,可以 try catch,然后在 catch 中 return false 就可以控制事务回滚了,然后通过得到 Db.tx(...) 方法的返回值再控制对上层响应什么返回值会更方便