diff --git a/kernel-d-seata/README.md b/kernel-d-seata/README.md
new file mode 100644
index 000000000..aff0b4426
--- /dev/null
+++ b/kernel-d-seata/README.md
@@ -0,0 +1 @@
+分布式事务Seata模块
diff --git a/kernel-d-seata/db/db.sql b/kernel-d-seata/db/db.sql
new file mode 100644
index 000000000..dbd4925a7
--- /dev/null
+++ b/kernel-d-seata/db/db.sql
@@ -0,0 +1,111 @@
+
+-- ----------------------------
+-- 订单库
+-- ----------------------------
+DROP DATABASE IF EXISTS `order`;
+CREATE DATABASE IF NOT EXISTS `order` DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;
+
+USE `order`;
+
+DROP TABLE IF EXISTS `order_info`;
+CREATE TABLE `order_info` (
+ `order_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单ID',
+ `product_id` bigint(20) NOT NULL COMMENT '商品ID',
+ `user_id` bigint(20) NOT NULL COMMENT '用户ID',
+ `prod_price` double(8, 2) NOT NULL COMMENT '商品单价',
+ `prod_number` int(11) NOT NULL COMMENT '商品数量',
+ `total_amount` double(10, 2) NOT NULL COMMENT '总价',
+ `pay_status` int(11) NOT NULL COMMENT '支付状态:1待支付,2已支付,3支付失败,已取消',
+ `create_user` bigint(20) NULL DEFAULT NULL COMMENT '创建者',
+ `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+ `update_user` bigint(20) NULL DEFAULT NULL COMMENT '更新者',
+ `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
+ `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ PRIMARY KEY (`order_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '订单表' ROW_FORMAT = Dynamic;
+
+DROP TABLE IF EXISTS `undo_log`;
+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,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT = 'seata事务记录';
+
+
+-- ----------------------------
+-- 仓储库
+-- ----------------------------
+DROP DATABASE IF EXISTS `storage`;
+CREATE DATABASE IF NOT EXISTS `storage` DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;
+
+USE `storage`;
+
+DROP TABLE IF EXISTS `product_info`;
+CREATE TABLE `product_info` (
+ `prod_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '商品ID',
+ `prod_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商品名称',
+ `inventory` int(11) NOT NULL COMMENT '库存数量',
+ `prod_price` double(8, 2) NOT NULL COMMENT '商品单价',
+ `prod_status` int(11) NOT NULL COMMENT '上架状态:1上架,2下架',
+ `create_user` bigint(20) NULL DEFAULT NULL COMMENT '创建者',
+ `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+ `update_user` bigint(20) NULL DEFAULT NULL COMMENT '更新者',
+ `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
+ `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ PRIMARY KEY (`prod_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品表' ROW_FORMAT = Dynamic;
+
+DROP TABLE IF EXISTS `undo_log`;
+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,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT = 'seata事务记录';
+
+
+-- ----------------------------
+-- 用户库
+-- ----------------------------
+DROP DATABASE IF EXISTS `member`;
+CREATE DATABASE IF NOT EXISTS `member` DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;
+
+USE `member`;
+
+DROP TABLE IF EXISTS `member_wallet`;
+CREATE TABLE `member_wallet` (
+ `member_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '会员ID',
+ `member_balance` double(8, 2) DEFAULT '0.00' COMMENT '会员余额',
+ `member_integral` double(8, 2) DEFAULT '0.00' COMMENT '会员积分',
+ `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+ `update_user` bigint(20) NULL DEFAULT NULL COMMENT '更新者',
+ `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`member_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户钱包' ROW_FORMAT = Dynamic;
+
+DROP TABLE IF EXISTS `undo_log`;
+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,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT = 'seata事务记录';
diff --git a/kernel-d-seata/doc/seata使用手册.docx b/kernel-d-seata/doc/seata使用手册.docx
new file mode 100644
index 000000000..9b129bfc0
Binary files /dev/null and b/kernel-d-seata/doc/seata使用手册.docx differ
diff --git a/kernel-d-seata/pom.xml b/kernel-d-seata/pom.xml
new file mode 100644
index 000000000..cf5b61599
--- /dev/null
+++ b/kernel-d-seata/pom.xml
@@ -0,0 +1,33 @@
+
+
+
+ cn.stylefeng.roses
+ roses-kernel
+ 7.0.2
+ ../pom.xml
+
+ 4.0.0
+
+ kernel-d-seata
+
+ pom
+
+ seata-demo-wallet-api
+ seata-demo-storage-api
+ seata-demo-order
+
+
+
+
+
+
+ cn.stylefeng.roses
+ kernel-a-rule
+ 7.0.2
+
+
+
+
+
diff --git a/kernel-d-seata/seata-demo-order/pom.xml b/kernel-d-seata/seata-demo-order/pom.xml
new file mode 100644
index 000000000..1c6503889
--- /dev/null
+++ b/kernel-d-seata/seata-demo-order/pom.xml
@@ -0,0 +1,41 @@
+
+
+
+ cn.stylefeng.roses
+ kernel-d-seata
+ 7.0.2
+ ../pom.xml
+
+ 4.0.0
+
+ seata-demo-order
+
+ jar
+
+
+ org.springframework.cloud
+ spring-cloud-openfeign-core
+ 2.2.6.RELEASE
+
+
+ cn.stylefeng.roses
+ seata-demo-storage-api
+ 7.0.2
+ compile
+
+
+ cn.stylefeng.roses
+ seata-demo-wallet-api
+ 7.0.2
+ compile
+
+
+ io.seata
+ seata-all
+ 1.3.0
+
+
+
+
diff --git a/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/consumer/StorageConsumer.java b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/consumer/StorageConsumer.java
new file mode 100644
index 000000000..acf94aa9f
--- /dev/null
+++ b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/consumer/StorageConsumer.java
@@ -0,0 +1,13 @@
+package cn.stylefeng.roses.kernel.seata.order.consumer;
+
+import cn.stylefeng.roses.kernel.seata.api.StorageApi;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * 仓储api
+ * @author wangyl
+ * @Date 2021-04-10 9:25:13
+ */
+@FeignClient(name = "seata-demo-storage")
+public interface StorageConsumer extends StorageApi {
+}
diff --git a/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/consumer/WalletConsumer.java b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/consumer/WalletConsumer.java
new file mode 100644
index 000000000..09031948d
--- /dev/null
+++ b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/consumer/WalletConsumer.java
@@ -0,0 +1,13 @@
+package cn.stylefeng.roses.kernel.seata.order.consumer;
+
+import cn.stylefeng.roses.kernel.seata.wallet.api.WalletApi;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * 用户钱包api
+ * @author wangyl
+ * @Date 2021-04-10 9:25:13
+ */
+@FeignClient(name = "seata-demo-wallet")
+public interface WalletConsumer extends WalletApi {
+}
diff --git a/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/controller/OrderController.java b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/controller/OrderController.java
new file mode 100644
index 000000000..00059c054
--- /dev/null
+++ b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/controller/OrderController.java
@@ -0,0 +1,26 @@
+package cn.stylefeng.roses.kernel.seata.order.controller;
+
+import cn.stylefeng.roses.kernel.seata.order.entity.Order;
+import cn.stylefeng.roses.kernel.seata.order.service.OrderService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+
+/**
+ * 订单接口
+ * @author wangyl
+ * @Date 2021-04-10 9:25:13
+ */
+public class OrderController {
+
+ @Autowired
+ OrderService orderService;
+
+ /**
+ * 创建订单
+ */
+ @GetMapping("/create")
+ Order create(String userId, String commodityCode, int orderCount){
+ return orderService.create(userId,commodityCode,orderCount);
+ }
+
+}
diff --git a/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/entity/Order.java b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/entity/Order.java
new file mode 100644
index 000000000..36ecb95cf
--- /dev/null
+++ b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/entity/Order.java
@@ -0,0 +1,116 @@
+package cn.stylefeng.roses.kernel.seata.order.entity;
+
+import java.io.Serializable;
+import java.util.Date;
+
+public class Order implements Serializable {
+
+ private Long orderId;
+ private Long productId;
+ private Long userId;
+ private Integer prodPrice;
+ private Integer prodNumber;
+ private Integer totalAmount;
+ private Integer payStatus;
+ private Long createUser;
+ private Date createTime;
+ private Long updateUser;
+ private Date updateTime;
+ private String remark;
+
+ public Long getOrderId() {
+ return orderId;
+ }
+
+ public void setOrderId(Long orderId) {
+ this.orderId = orderId;
+ }
+
+ public Long getProductId() {
+ return productId;
+ }
+
+ public void setProductId(Long productId) {
+ this.productId = productId;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+
+ public void setUserId(Long userId) {
+ this.userId = userId;
+ }
+
+ public Integer getProdPrice() {
+ return prodPrice;
+ }
+
+ public void setProdPrice(Integer prodPrice) {
+ this.prodPrice = prodPrice;
+ }
+
+ public Integer getProdNumber() {
+ return prodNumber;
+ }
+
+ public void setProdNumber(Integer prodNumber) {
+ this.prodNumber = prodNumber;
+ }
+
+ public Integer getTotalAmount() {
+ return totalAmount;
+ }
+
+ public void setTotalAmount(Integer totalAmount) {
+ this.totalAmount = totalAmount;
+ }
+
+ public Integer getPayStatus() {
+ return payStatus;
+ }
+
+ public void setPayStatus(Integer payStatus) {
+ this.payStatus = payStatus;
+ }
+
+ public Long getCreateUser() {
+ return createUser;
+ }
+
+ public void setCreateUser(Long createUser) {
+ this.createUser = createUser;
+ }
+
+ public Date getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ public Long getUpdateUser() {
+ return updateUser;
+ }
+
+ public void setUpdateUser(Long updateUser) {
+ this.updateUser = updateUser;
+ }
+
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+
+ public String getRemark() {
+ return remark;
+ }
+
+ public void setRemark(String remark) {
+ this.remark = remark;
+ }
+}
diff --git a/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/mapper/OrderMapper.java b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/mapper/OrderMapper.java
new file mode 100644
index 000000000..edd600268
--- /dev/null
+++ b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/mapper/OrderMapper.java
@@ -0,0 +1,16 @@
+package cn.stylefeng.roses.kernel.seata.order.mapper;
+
+import cn.stylefeng.roses.kernel.seata.order.entity.Order;
+
+/**
+ * 数据层
+ *
+ * @author wangyl
+ */
+public interface OrderMapper {
+
+ void insertOrder(Order order);
+
+ Order selectById(Long orderId);
+
+}
diff --git a/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/mapper/mapping/OrderMapper.xml b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/mapper/mapping/OrderMapper.xml
new file mode 100644
index 000000000..192054e36
--- /dev/null
+++ b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/mapper/mapping/OrderMapper.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+ insert into order(
+ product_id,
+ user_id,
+ prod_price,
+ prod_number,
+ total_amount,
+ pay_status,
+ create_user,
+ create_time
+ update_user,
+ update_time,
+ remark,
+ )values(
+ #{productId},
+ #{userId},
+ #{prodPrice},
+ #{prodNumber},
+ #{totalAmount},
+ #{payStatus},
+ #{createUser},
+ #{createTime}
+ #{updateUser},
+ #{updateTime},
+ #{remark},
+ )
+
+
+
+
+
diff --git a/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/service/OrderService.java b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/service/OrderService.java
new file mode 100644
index 000000000..78d2f299c
--- /dev/null
+++ b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/service/OrderService.java
@@ -0,0 +1,9 @@
+package cn.stylefeng.roses.kernel.seata.order.service;
+
+import cn.stylefeng.roses.kernel.seata.order.entity.Order;
+
+public interface OrderService {
+
+ Order create(String userId, String commodityCode, int orderCount);
+
+}
diff --git a/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/service/impl/OrderServiceImpl.java b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/service/impl/OrderServiceImpl.java
new file mode 100644
index 000000000..90ef8510e
--- /dev/null
+++ b/kernel-d-seata/seata-demo-order/src/main/java/cn/stylefeng/roses/kernel/seata/order/service/impl/OrderServiceImpl.java
@@ -0,0 +1,41 @@
+package cn.stylefeng.roses.kernel.seata.order.service.impl;
+
+import cn.stylefeng.roses.kernel.seata.order.consumer.StorageConsumer;
+import cn.stylefeng.roses.kernel.seata.order.consumer.WalletConsumer;
+import cn.stylefeng.roses.kernel.seata.order.entity.Order;
+import cn.stylefeng.roses.kernel.seata.order.mapper.OrderMapper;
+import cn.stylefeng.roses.kernel.seata.order.service.OrderService;
+import io.seata.spring.annotation.GlobalTransactional;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class OrderServiceImpl implements OrderService {
+
+ @Autowired
+ private StorageConsumer storageConsumer;
+ @Autowired
+ private WalletConsumer walletConsumer;
+ @Autowired
+ private OrderMapper orderMapper;
+
+ /**
+ * 分布式事务跨库操作,起始位置,使用@GlobalTransactional注解修饰
+ * @param userId
+ * @param commodityCode
+ * @param orderCount
+ * @return
+ */
+ @GlobalTransactional(rollbackFor = Exception.class)
+ @Override
+ public Order create(String userId, String commodityCode, int orderCount) {
+ Order order = new Order();
+ //保存订单
+ orderMapper.insertOrder(order);
+ //扣减商品库存
+ storageConsumer.deduct(commodityCode,orderCount);
+ //扣用户钱
+ walletConsumer.debit(userId,order.getTotalAmount());
+ return order;
+ }
+}
diff --git a/kernel-d-seata/seata-demo-storage-api/pom.xml b/kernel-d-seata/seata-demo-storage-api/pom.xml
new file mode 100644
index 000000000..8bfb389a4
--- /dev/null
+++ b/kernel-d-seata/seata-demo-storage-api/pom.xml
@@ -0,0 +1,17 @@
+
+
+
+ cn.stylefeng.roses
+ kernel-d-seata
+ 7.0.2
+ ../pom.xml
+
+ 4.0.0
+
+ seata-demo-storage-api
+
+ jar
+
+
diff --git a/kernel-d-seata/seata-demo-storage-api/src/main/java/cn/stylefeng/roses/kernel/seata/api/StorageApi.java b/kernel-d-seata/seata-demo-storage-api/src/main/java/cn/stylefeng/roses/kernel/seata/api/StorageApi.java
new file mode 100644
index 000000000..f45a7b30a
--- /dev/null
+++ b/kernel-d-seata/seata-demo-storage-api/src/main/java/cn/stylefeng/roses/kernel/seata/api/StorageApi.java
@@ -0,0 +1,16 @@
+package cn.stylefeng.roses.kernel.seata.api;
+
+/**
+ * 仓储api
+ *
+ * @author wangyl
+ * @date 2021-04-11 9:52:31
+ */
+public interface StorageApi {
+
+ /**
+ * 扣除存储数量
+ */
+ void deduct(String commodityCode, int count);
+
+}
diff --git a/kernel-d-seata/seata-demo-wallet-api/pom.xml b/kernel-d-seata/seata-demo-wallet-api/pom.xml
new file mode 100644
index 000000000..6bae3c51b
--- /dev/null
+++ b/kernel-d-seata/seata-demo-wallet-api/pom.xml
@@ -0,0 +1,17 @@
+
+
+
+ cn.stylefeng.roses
+ kernel-d-seata
+ 7.0.2
+ ../pom.xml
+
+ 4.0.0
+
+ seata-demo-wallet-api
+
+ jar
+
+
diff --git a/kernel-d-seata/seata-demo-wallet-api/src/main/java/cn/stylefeng/roses/kernel/seata/wallet/api/WalletApi.java b/kernel-d-seata/seata-demo-wallet-api/src/main/java/cn/stylefeng/roses/kernel/seata/wallet/api/WalletApi.java
new file mode 100644
index 000000000..c7caa0ae7
--- /dev/null
+++ b/kernel-d-seata/seata-demo-wallet-api/src/main/java/cn/stylefeng/roses/kernel/seata/wallet/api/WalletApi.java
@@ -0,0 +1,16 @@
+package cn.stylefeng.roses.kernel.seata.wallet.api;
+
+/**
+ * 用户钱包api
+ *
+ * @author wangyl
+ * @date 2021-04-10 8:56:48
+ */
+public interface WalletApi {
+
+ /**
+ * 从用户账户中借出
+ */
+ void debit(String userId, int money);
+
+}
diff --git a/pom.xml b/pom.xml
index 6004ce866..2f053ec18 100644
--- a/pom.xml
+++ b/pom.xml
@@ -94,6 +94,9 @@
kernel-s-system
+
+ kernel-d-seata
+