在bfxy-store-api模块里新增一个接口
package com.bfxy.store.service.api;
import java.util.Date;
public interface StoreServiceApi {
int selectVersion(String supplierId, String goodsId);
int updateStoreCountByVersion(int version, String supplierId, String goodIds, String updateBy, Date updateTime);
int selectStoreCount(String supplierId, String goodsId);
}
在bfxy-order模块中新增的代码如下
package com.bfxy.order.web;
import com.bfxy.order.service.OrderService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@RequestMapping("/createOrder")
public String createOrder(@RequestParam("cityId") String cityId,
@RequestParam("platformId") String platformId,
@RequestParam("userId") String userId,
@RequestParam("suppliedId") String suppliedId,
@RequestParam("goodsId") String goodsId) throws InterruptedException {
return orderService.createOrder(cityId, platformId, userId, suppliedId, goodsId) ? "下单成功" : "下单失败";
}
}
package com.bfxy.order.constants;
public enum OrderStatus {
ORDER_CREATED("1"),
ORDER_PAYED("2"),
ORDER_FAIL("3");
private String status;
OrderStatus(String status) {
this.status = status;
}
public String getValue() {
return status;
}
}
package com.bfxy.order.service;
public interface OrderService {
boolean createOrder(String cityId, String platformId, String userId, String suppliedId, String goodsId);
}
package com.bfxy.order.service.impl;
import com.alibaba.dubbo.config.annotation.Reference;
import com.bfxy.order.constants.OrderStatus;
import com.bfxy.order.entity.Order;
import com.bfxy.order.mapper.OrderMapper;
import com.bfxy.order.service.OrderService;
import com.bfxy.store.service.api.StoreServiceApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.UUID;
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Reference(
version = "1.0.0",
application = "${dubbo.application.id}",
interfaceName = "com.bfxy.store.service.api.StoreServiceApi",
check = false,
timeout = 3000,
retries = 0 //读请求允许重试3次,写请求不要进行重试
)
private StoreServiceApi storeServiceApi;
@Override
public boolean createOrder(String cityId, String platformId, String userId, String suppliedId, String goodsId) {
boolean flag = true;
try {
Order order = new Order();
order.setOrderId(UUID.randomUUID().toString());
order.setOrderType("1");
order.setCityId(cityId);
order.setPlatformId(platformId);
order.setUserId(userId);
order.setSupplierId(suppliedId);
order.setGoodsId(goodsId);
order.setOrderStatus(OrderStatus.ORDER_CREATED.getValue());
order.setRemark("");
order.setCreateBy("admin");
order.setCreateTime(new Date());
order.setUpdateBy("admin");
order.setUpdateTime(new Date());
int currentVersion = storeServiceApi.selectVersion(suppliedId, goodsId);
int updateRetCount = storeServiceApi.updateStoreCountByVersion(currentVersion, suppliedId, goodsId, "admin", new Date());
if (updateRetCount == 1) {
//TODO 如果出现SQL异常入库失败,那么要对库存的数量和版本号进行回滚操作
orderMapper.insertSelective(order);
}
//没有更新成功:1.高并发时乐观锁生效,2.库存不足
else if (updateRetCount == 0) {
flag = false;//下单标识失败
int currentStoreCount = storeServiceApi.selectStoreCount(suppliedId, goodsId);
if (currentStoreCount == 0) {
System.err.println("-----当前库存不足...");
} else {
System.err.println("-----乐观锁生效...");
}
}
} catch (Exception e) {
e.printStackTrace();
// 具体捕获的异常是什么异常
flag = false;
}
return flag;
}
}
在bfxy-store新增以下代码
package com.bfxy.store.service.provider;
import com.alibaba.dubbo.config.annotation.Service;
import com.bfxy.store.mapper.StoreMapper;
import com.bfxy.store.service.api.StoreServiceApi;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;
@Service(
version = "1.0.0",
application = "${dubbo.application.id}",
protocol = "${dubbo.protocol.id}",
registry = "${dubbo.registry.id}"
)
public class StoreServiceProvider implements StoreServiceApi {
@Autowired
private StoreMapper storeMapper;
@Override
public int selectVersion(String supplierId, String goodsId) {
return storeMapper.selectVersion(supplierId, goodsId);
}
@Override
public int updateStoreCountByVersion(int version, String supplierId, String goodIds, String updateBy, Date updateTime) {
return storeMapper.updateStoreCountByVersion(version, supplierId, goodIds, updateBy, updateTime);
}
@Override
public int selectStoreCount(String supplierId, String goodsId) {
return storeMapper.selectStoreCount(supplierId, goodsId);
}
}
在bfxy-store模块下的StoreMapper.xml新增以下三个查询
<select id="selectVersion" resultType="int">
select version from t_store ts
where ts.supplier_id = #{supplierId,jdbcType=VARCHAR}
and
ts.goods_id = #{goodsId,jdbcType=VARCHAR}
</select>
<update id="updateStoreCountByVersion">
update t_store ts
set
store_count = store_count - 1,
version = version + 1,
update_by = #{updateBy,jdbcType=VARCHAR},
update_time = #{updateTime,jdbcType=TIMESTAMP}
where ts.supplier_id = #{supplierId,jdbcType=VARCHAR}
and
ts.goods_id = #{goodsId,jdbcType=VARCHAR}
and
ts.version = #{version,jdbcType=INTEGER}
and
ts.store_count > 0
</update>
<select id="selectStoreCount" resultType="int">
select store_count from t_store ts
where ts.supplier_id = #{supplierId,jdbcType=VARCHAR}
and
ts.goods_id = #{goodsId,jdbcType=VARCHAR}
</select>