spring aop事务支持与synchronized的问题
2018-03-14 19:51
399 查看
环境:国土交易系统网上出价、限时竞价阶段同一个时间点多人出价,需要保证金额大的竞买人一定能出价,并且时间在排序列表中也最大。
为了防止幻读在service层方法上加了synchronized还是出现了幻读的情况解决办法 把synchronized加到Controller层或者大于事务边界的调用层原因 使用了spring aop事务,事务提交在一个service方法执行完毕后,可能事务还没有提交,这时候另外一个线程开始执行synchronized方法导致并发问题出现代码片段如下:Controller private static Object lock=new Object();
* 方法描述 : 保存挂牌限时信息
* @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,锁依然没有生效!
为了防止幻读在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,锁依然没有生效!
相关文章推荐
- spring中事务和aop的顺序问题二(配置形式)
- Spring中解决Aop 事务嵌套回滚问题
- 一站式异常处理(spring AOP事务回滚问题)
- Spring AOP 事务问题
- 【转】Spring中事务与aop的先后顺序问题
- Spring AOP 事务问题
- Spring中事务与aop的先后顺序问题
- Spring AOP 事务问题
- spring配置hibernate事务aop不生效的问题
- spring事务和aop问题小结
- Spring中事务与aop的先后顺序问题
- Spring中事务与aop的先后顺序问题
- 使用spring声明式事务,spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务。
- spring(基础18) Sprin事务和synchronized锁的一些问题
- spring事务和synchronized锁的一些问题
- Spring aop事务先后问题
- Spring中事务与aop的先后顺序问题
- spring AOP 配置事务不起作用的问题(用Junit测试service)
- Spring中事务与aop的先后顺序问题(注解形式)
- Spring中事务与aop的先后顺序问题