Mysql 死锁,但是执行过程却是null终极问题解决
出现如下幽灵语句
这个表在这:
问题代码:
/**
* 对投注项目进行投注
* @param roomId
* @param gameId
* @param gameItemId
* @param putScore
* @param multiPower
* @param req
* @return
*/
@SuppressWarnings("unused")
@At("/betQBH")
@Authentication(checkarea=AuthenticationType.session)
@POST
public Object betQBH( @Param("roomId")String roomId, @Param("gameId")String gameId,
@Param("gameItemId")String gameItemId, @Param("putScore")Integer putScore, @Param("multiPower")Double multiPower, HttpServletRequest req) {
try {
//这个选项是没有用的
multiPower = 1.00d;
// 校验空错误
ApiResult checkResult = QBH_ResultUtil.checkStringParamWhenError(QBH_ResultUtil.getResultError(),
new String[] { "roomId参数错误" ,"gameId参数错误","gameItemId参数错误"}, new String[] { roomId,gameId,gameItemId});
if (checkResult != null)
return checkResult;
Member mb = (Member) req.getAttribute("member");
Game game = gameService.fetch(gameId);
//竞猜项目状态为 0停止投注 及 2已结算的会列出来,但不能投注
if (game.getState() == null) game.setState(1);
if (game.getState() == GameConstants.GG_STATE_CANNOTBET) {
return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "此竞猜项目暂时停止投注",new JsonObject());
}
if (game.getState() == GameConstants.GG_STATE_CLOSING) {
return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "此竞猜项目已结算",new JsonObject());
}
//jonathan add
/*GameSchedule gameSchedule=gameScheduleService.fetch(game.getMatchId());
if(gameSchedule==null || gameSchedule.getState()==GameConstants.GS_STATE_GAMEOVER)
{
return ApiResult.New(ReturnCode.ERROR).addMsg("此竞猜项目暂时停止投注");
}*/
GameItem item=gameItemService.fetch(gameItemId);
if (item.getState() == null) item.setState(1);
if (item.getState() != GameConstants.GG_STATE_CANBET) {
return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "此竞猜项目暂时停止投注",new JsonObject());
}
/*if(multiPower==null || StringUtils.isBlank(item.getOdds())||multiPower.doubleValue()!=Double.valueOf(item.getOdds()))
{
return ApiResult.New(ReturnCode.ERROR).addMsg("此竞猜项目赔率已发生变化,请重新下注!"+multiPower+"-"+item.getOdds());
}*/
// 查询该用户是否已经投注过该竞猜项目(竞猜的其中一种结果),有返回true,无返回false
/*int alrdyBetCnt = roomMembersBetService.count(Cnd.NEW().and("memberId", "=", mb.getId()).and("gameItemId", "=", gameItemId).and("gameId", "=", gameId));
if (alrdyBetCnt > 0) {
return ApiResult.New(ReturnCode.ERROR).addMsg("竞猜项目不支持重复投注");
}*/
// 验证投注积分值处于有效范围
if (putScore<game.getMinScore() || putScore>game.getMaxScore()) {
return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "投注积分区间["+game.getMinScore()+" - "+game.getMaxScore()+"]",new JsonObject());
}
try
{
Trans.begin();
//betInner( roomId, game, item, putScore, multiPower, req);
// 查询该房间的所在赛程的ID
String scheduleId = game.getMatchId();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
mb = memberService.fetch(mb.getId());// 从数据库中读出新数据。
// 首页、房间投注逻辑
if (Strings.isBlank(roomId) || roomId.equals("0") || roomId.trim().equals("")) { // 首页投注
if (mb.getTotalScore() < putScore) {
return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "成员当前总积分:" + mb.getTotalScore() + " 小于投注积分数:" + putScore + "",new JsonObject());
}
mb.setTotalScore(mb.getTotalScore() - putScore);
} else { // 房间投注
// (判断大小房:0大房 1小房) 前边括号注释的逻辑失效
int roomType = roomService.query(Cnd.NEW().and("id", "=", roomId)).get(0).getType();
if (mb.getTotalScore() < putScore) {
return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "积分不足!缺少 " + (putScore - mb.getTotalScore()) + "积分" + putScore + "",new JsonObject());
}
mb.setTotalScore(mb.getTotalScore() - putScore);
/*if (roomType == RoomConstants.RR_TYPE_BIG) { // 大房投注的积分直接扣除
if (mb.getTotalScore() < putScore) {
throw new Exception("积分不足!缺少 " + (putScore - mb.getTotalScore()) + "积分");
}
mb.setTotalScore(mb.getTotalScore() - putScore);
} else { // 小房只允许用 冻结积分表的可用积分进行投注
RoomMembersSealInfo sealInfo = roomMembersSealInfoService
.fetch(Cnd.NEW().and("membersId", "=", mb.getId()).and("roomId", "=", roomId));
if (sealInfo != null) {
if (sealInfo.getAvlScore() < putScore) {
throw new Exception("房间内可用积分不足!缺少 " + (putScore - sealInfo.getAvlScore()) + "积分");
}
sealInfo.setAvlScore(sealInfo.getAvlScore() - putScore);
roomMembersSealInfoService.update(sealInfo);
} else {
// return ApiResult.New(ReturnCode.ERROR).addMsg("请重新进入房间");
throw new Exception("请重新进入房间");
}
}*/
}
int count = Integer.parseInt(mb.getBetCount()) + 1;
mb.setBetCount(count + "");
memberService.update(mb);
RoomMembersBet membersBet = new RoomMembersBet(mb.getId(), roomId, game.getId(), item.getId(), scheduleId, 0,
putScore, sdf.format(new Date(System.currentTimeMillis())), multiPower);
RoomMembersBet roomMembersBet = roomMembersBetService.insert(membersBet);
// 积分记录表 插入一条积分消费记录
memberScoreRecordService.insert(new MemberScoreRecord(mb.getId(), "投注" + putScore + "积分",
MemberConstants.MSR_TYPE_EXPEND, putScore.longValue(), 0l, roomMembersBet.getId(), roomId));
Trans.commit();
}
catch (Exception ex) {
Trans.rollback();
ex.printStackTrace();
log.error("投注发生错误:" + ex.getMessage());
return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "投注发生错误,请联系管理员",new JsonObject());
} finally {
Trans.close();
}
return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultSuccess(), ReturnCode.SUCCESS.getCode(), "投注成功",new JsonObject());
} catch (Exception e) {
e.printStackTrace();
log.error("投注发生错误:"+e.getMessage());
return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "投注发生错误,请联系管理员",new JsonObject());
}
}
简单而言,就是一个过程
Trans.begin();
return ;
Trans.commit();
Trans.rollback();
Trans.close();
事物执行的载体方法,被return语句从方法堆栈中移除了,但是mysql的事物并没有被结束掉
解决方法很简单:
return之前,关闭事物(回滚也可,根据业务)
总而言之,不要轻易在开启事物过程中return