您的位置:首页 > 编程语言 > Java开发

spring aop事务支持与synchronized的问题

2018-03-14 19:51 399 查看
环境:国土交易系统网上出价、限时竞价阶段同一个时间点多人出价,需要保证金额大的竞买人一定能出价,并且时间在排序列表中也最大。

为了防止幻读在service层方法上加了synchronized还是出现了幻读的情况解决办法 把synchronized加到Controller层或者大于事务边界的调用层原因 使用了spring aop事务,事务提交在一个service方法执行完毕后,可能事务还没有提交,这时候另外一个线程开始执行synchronized方法导致并发问题出现代码片段如下:Controller private static Object lock=new Object();
//保存出价信息
synchronized(lock){
saveFlag=limitBidBiz.saveBusLimitBidInfo(user.getPkId(), moneyDouble, busId,cert,user.getOrgId(), getRequest().getRemoteAddr(), signMoney, tranId);

//更新当前最高价
//busTranBiz.updateCurPriceByTranId(tranId, moneyDouble);
//更新挂牌截止时间
//busTranBiz.updateCurEtime(tranId, TimeHelper.addMinute(busTran.getTranEtime(), Constants.ASK_PERIOD));

if(saveFlag){
super.operateLog(Constants.LOG_TYPE_PAY,LogHelper.getLoginContent(busTran.getPkId(),moneyString,Constants.RES_LIMIT));
//有人出价,时间推移5分钟
busTranBiz.updateCurEtime(tranId, TimeHelper.addMinute(TimeHelper.getCurrentTime(), Constants.ASK_PERIOD));
if(houseState.equals(Constants.IS_TRUE)){
busBidderInfoBiz.updateIsLimitOrHouse(Constants.PRICE_HOUSE, tranId, user.getPkId());
}
//目前没有最高价限制,maxPriceConfig默认为0,moneyDouble为当前出价
double maxPriceConfig = busListConfig.getPriceMax();
if(moneyDouble==maxPriceConfig&&maxPriceConfig>0){
//出价额度达到最高价
boolean isProArea=busTranBiz.getIsReSetPriceOrHouseConfig(tranId, "00C");
//获取是否进行保障房竞拍
if(!isProArea){
//当前价格等于最高价且不需要进入保障房竞拍时直接调用成交定时任务(未加入)
busTran.setCurPrice(moneyDouble);
busResultBiz.tranSaction(busTran, getSessionUser().getPkId(), null);
}else{
//在限时竞价阶段增加5分钟,该五分钟为询问阶段,这里应该获取保存在bus_tran中的tran_etime,不应该取当前时间
busTranBiz.updateCurEtime(tranId, TimeHelper.addMinute(TimeHelper.getCurrentTime(), Constants.ASK_PERIOD));
//保障房定时任务处理
schedulerService.schedule(tranId, Constants.RES_LAND_TYPE, TimeHelper.getCurrentTime(), moneyDouble, getSessionUser().getPkId(), "111");

}
}else{
//定时任务处理
schedulerService.schedule(tranId, Constants.RES_LAND_TYPE, TimeHelper.getCurrentTime(), moneyDouble, getSessionUser().getPkId(), tranStep);
}
//保存出价日志信息
//super.operateLog(Constants.LOG_TYPE_PAY,LogHelper.getLoginContent(busTran.getPkId(),moneyString,Constants.RES_LIMIT));
//DWR消息分发
DwrService.perform(application,new String[]{"limitList",tranId});
state="succ";
}else{
super.operateLog(Constants.LOG_TYPE_PAY,LogHelper.getLoginContent(busTran.getPkId(),moneyString,Constants.RES_LIMIT));
//state="error|在您出价的时刻,其他竞买人的出价已经达到您的出价,您的出价无效!";
state="error|在您出价的时刻,其他竞买人的出价已经达到或超过您的出价,您的出价无效,若多次无法出价,请尝试刷新页面后再继续出价!";
}
}
service层:/**
* 方法描述 : 保存挂牌限时信息
* @param key
* @return
*/
@Transactional
public boolean saveBusLimitBidInfo(String accontId,Double price,String busId,String caCert,String orgId,String ip,String signPrice,String tranId){
//验证出价时间、价格都必须大于出价列表中的数据,保证出价列表中的价格、出价时间排序正确
String bidTime = TimeHelper.getCurrentMill();
List list=jdbcDao.findForList("select PK_ID from BUS_LIMIT_BID where TRAN_ID='"+tranId+"' and BID_PRICE >= "+ price + " or BID_TIME >= '" + bidTime + "'");
UserLogBiz userLogBiz = (UserLogBiz) SpringFactoryHelp.getApplicationContext().getBean("userLogBiz");
userLogBiz.operateLog(accontId, "price:" + price + " time:" + bidTime, "",orgId,"",tranId);
if(StringHelper.isEmptyList(list)){

//出价成功,保存竞价
BusLimitBid busLimit=new BusLimitBid();
busLimit.setPkId(GuidCreateHelper.getGuid());
busLimit.setAccountId(accontId);
busLimit.setBidPrice(price);
busLimit.setBidTime(bidTime);
busLimit.setBusId(busId);
busLimit.setCaCert(caCert);
busLimit.setOrgId(orgId);
busLimit.setPriceIp(ip);
busLimit.setSignPrice(signPrice);
busLimit.setTranId(tranId);
toolDao.save(busLimit);
busTranBiz.updateCurPriceByTranId(tranId, price);
return true;
}else{
//出价失败
return false;
}
}注意:synchronized(锁)中的锁线程必须使用同一个对象,如果不是同一个对象,即使加上synchronized,锁依然没有生效!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 事物