以下是说明文档里 声明式事务的源码:
@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(...) 方法的返回值再控制对上层响应什么返回值会更方便