This commit is contained in:
zhaohu
2026-06-12 16:14:58 +08:00
parent cf71897528
commit a7ba0f21e5
235 changed files with 33574 additions and 0 deletions
+30
View File
@@ -0,0 +1,30 @@
-- 创建 order库、业务表、undo_log表
create database seata_order;
use seata_order;
DROP TABLE IF EXISTS `tb_order`;
CREATE TABLE `tb_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` varchar(255) DEFAULT NULL,
`commodity_code` varchar(255) DEFAULT NULL,
`count` int(11) DEFAULT 0,
`money` int(11) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `undo_log`
(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`branch_id` BIGINT(20) NOT NULL,
`xid` VARCHAR(100) NOT NULL,
`context` VARCHAR(128) NOT NULL,
`rollback_info` LONGBLOB NOT NULL,
`log_status` INT(11) NOT NULL,
`log_created` DATETIME NOT NULL,
`log_modified` DATETIME NOT NULL,
`ext` VARCHAR(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8;
+27
View File
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>blade-example</artifactId>
<groupId>org.springblade</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>blade-seata-order</artifactId>
<name>${project.artifactId}</name>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-transaction</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,37 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.seata.order;
import org.springblade.common.constant.LauncherConstant;
import org.springblade.core.cloud.feign.EnableBladeFeign;
import org.springblade.core.launch.BladeApplication;
import org.springblade.core.transaction.annotation.SeataCloudApplication;
/**
* Order启动器
*
* @author Chill
*/
@EnableBladeFeign
@SeataCloudApplication
public class SeataOrderApplication {
public static void main(String[] args) {
BladeApplication.run(LauncherConstant.APPLICATION_SEATA_ORDER_NAME, SeataOrderApplication.class, args);
}
}
@@ -0,0 +1,34 @@
package org.springblade.seata.order.controller;
import lombok.AllArgsConstructor;
import org.springblade.core.tool.api.R;
import org.springblade.seata.order.service.IOrderService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* OrderController
*
* @author Chill
*/
@RestController
@RequestMapping("order")
@AllArgsConstructor
public class OrderController {
private final IOrderService orderService;
/**
* 创建订单
*
* @param userId 用户id
* @param commodityCode 商品代码
* @param count 数量
* @return boolean
*/
@RequestMapping("/create")
public R createOrder(String userId, String commodityCode, Integer count) {
return R.status(orderService.createOrder(userId, commodityCode, count));
}
}
@@ -0,0 +1,33 @@
package org.springblade.seata.order.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* Order
*
* @author Chill
*/
@Data
@Accessors(chain = true)
@TableName("tb_order")
public class Order implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String userId;
private String commodityCode;
private Integer count;
private BigDecimal money;
}
@@ -0,0 +1,25 @@
package org.springblade.seata.order.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* StorageClient
*
* @author Chill
*/
@FeignClient(name = "blade-seata-storage", fallback = StorageClientFallback.class)
public interface IStorageClient {
/**
* 减库存
*
* @param commodityCode 商品代码
* @param count 数量
* @return boolean
*/
@GetMapping("/storage/deduct")
int deduct(@RequestParam("commodityCode") String commodityCode, @RequestParam("count") Integer count);
}
@@ -0,0 +1,18 @@
package org.springblade.seata.order.feign;
import org.springframework.stereotype.Component;
/**
* StorageClientFallback
*
* @author Chill
*/
@Component
public class StorageClientFallback implements IStorageClient {
@Override
public int deduct(String commodityCode, Integer count) {
return -1;
}
}
@@ -0,0 +1,12 @@
package org.springblade.seata.order.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.seata.order.entity.Order;
/**
* OrderMapper
*
* @author Chill
*/
public interface OrderMapper extends BaseMapper<Order> {
}
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.seata.order.mapper.OrderMapper">
</mapper>
@@ -0,0 +1,23 @@
package org.springblade.seata.order.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.seata.order.entity.Order;
/**
* IOrderService
*
* @author Chill
*/
public interface IOrderService extends IService<Order> {
/**
* 创建订单
*
* @param userId 用户id
* @param commodityCode 商品代码
* @param count 数量
* @return boolean
*/
boolean createOrder(String userId, String commodityCode, Integer count);
}
@@ -0,0 +1,48 @@
package org.springblade.seata.order.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.AllArgsConstructor;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.seata.order.entity.Order;
import org.springblade.seata.order.feign.IStorageClient;
import org.springblade.seata.order.mapper.OrderMapper;
import org.springblade.seata.order.service.IOrderService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
/**
* OrderServiceImpl
*
* @author Chill
*/
@Service
@AllArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
private final IStorageClient storageClient;
@Override
@GlobalTransactional
@Transactional(rollbackFor = Exception.class)
public boolean createOrder(String userId, String commodityCode, Integer count) {
int maxCount = 100;
BigDecimal orderMoney = new BigDecimal(count).multiply(new BigDecimal(5));
Order order = new Order()
.setUserId(userId)
.setCommodityCode(commodityCode)
.setCount(count)
.setMoney(orderMoney);
int cnt1 = baseMapper.insert(order);
int cnt2 = storageClient.deduct(commodityCode, count);
if (cnt2 < 0) {
throw new ServiceException("创建订单失败");
} else if (count > maxCount) {
throw new ServiceException("超过订单最大值,创建订单失败");
}
return cnt1 > 0 && cnt2 > 0;
}
}
@@ -0,0 +1,15 @@
#服务器端口
server:
port: 8501
#数据源配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/seata_order?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
username: root
password: root
#常规配置
blade:
mybatis-plus:
tenant-mode: false