From 8b1a03a7a026b5feb9fcaa1d6463cbad2066504c Mon Sep 17 00:00:00 2001
From: YunaiV <>
Date: Thu, 2 Apr 2020 19:25:04 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20seata=20=E6=9C=8D=E5=8A=A1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/resources/application.yaml | 2 +-
lab-52/lab-52-multiple-datasource/pom.xml | 6 +-
...torageService.java => ProductService.java} | 4 +-
...rviceImpl.java => AccountServiceImpl.java} | 4 +-
.../service/impl/OrderServiceImpl.java | 10 +--
...rviceImpl.java => ProductServiceImpl.java} | 10 +--
.../src/main/resources/application.yaml | 10 +--
.../src/main/resources/data.sql | 83 +++++++++++++++++++
lab-53/lab-53-seata-at-dubbo-demo/data.sql | 82 ++++++++++++++++++
.../pom.xml | 14 ++++
.../accountservice/api/AccountService.java | 17 ++++
.../pom.xml | 73 ++++++++++++++++
.../AccountServiceApplication.java | 13 +++
.../lab53/accountservice/dao/AccountDao.java | 32 +++++++
.../service/AccountServiceImpl.java | 48 +++++++++++
.../src/main/resources/application.yaml | 38 +++++++++
.../pom.xml | 14 ++++
.../lab53/orderservice/api/OrderService.java | 19 +++++
.../pom.xml | 83 +++++++++++++++++++
.../orderservice/OrderServiceApplication.java | 13 +++
.../controller/OrderController.java | 29 +++++++
.../lab53/orderservice/dao/OrderDao.java | 23 +++++
.../lab53/orderservice/entity/OrderDO.java | 56 +++++++++++++
.../service/OrderServiceImpl.java | 51 ++++++++++++
.../src/main/resources/application.yaml | 41 +++++++++
.../pom.xml | 14 ++++
.../storageservice/api/ProductService.java | 17 ++++
.../pom.xml | 73 ++++++++++++++++
.../ProductServiceApplication.java | 13 +++
.../lab53/productservice/dao/ProductDao.java | 33 ++++++++
.../service/ProductService.java | 17 ++++
.../src/main/resources/application.yaml | 38 +++++++++
lab-53/lab-53-seata-at-dubbo-demo/pom.xml | 24 ++++++
lab-53/pom.xml | 20 +++++
pom.xml | 1 +
35 files changed, 1002 insertions(+), 23 deletions(-)
rename lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/{StorageService.java => ProductService.java} (85%)
rename lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/{AmountServiceImpl.java => AccountServiceImpl.java} (95%)
rename lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/{StorageServiceImpl.java => ProductServiceImpl.java} (85%)
create mode 100644 lab-52/lab-52-multiple-datasource/src/main/resources/data.sql
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/data.sql
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service-api/pom.xml
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service-api/src/main/java/cn/iocoder/springboot/lab53/accountservice/api/AccountService.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/pom.xml
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/java/cn/iocoder/springboot/lab53/accountservice/AccountServiceApplication.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/java/cn/iocoder/springboot/lab53/accountservice/dao/AccountDao.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/java/cn/iocoder/springboot/lab53/accountservice/service/AccountServiceImpl.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/resources/application.yaml
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service-api/pom.xml
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service-api/src/main/java/cn/iocoder/springboot/lab53/orderservice/api/OrderService.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/pom.xml
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/OrderServiceApplication.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/controller/OrderController.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/dao/OrderDao.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/entity/OrderDO.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/service/OrderServiceImpl.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/resources/application.yaml
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service-api/pom.xml
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service-api/src/main/java/cn/iocoder/springboot/lab53/storageservice/api/ProductService.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/pom.xml
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/java/cn/iocoder/springboot/lab53/productservice/ProductServiceApplication.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/java/cn/iocoder/springboot/lab53/productservice/dao/ProductDao.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/java/cn/iocoder/springboot/lab53/productservice/service/ProductService.java
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/resources/application.yaml
create mode 100644 lab-53/lab-53-seata-at-dubbo-demo/pom.xml
create mode 100644 lab-53/pom.xml
diff --git a/lab-30/lab-30-dubbo-annotations-demo/user-rpc-service-provider-02/src/main/resources/application.yaml b/lab-30/lab-30-dubbo-annotations-demo/user-rpc-service-provider-02/src/main/resources/application.yaml
index aa61f2aa0..58798bdb5 100644
--- a/lab-30/lab-30-dubbo-annotations-demo/user-rpc-service-provider-02/src/main/resources/application.yaml
+++ b/lab-30/lab-30-dubbo-annotations-demo/user-rpc-service-provider-02/src/main/resources/application.yaml
@@ -14,7 +14,7 @@ dubbo:
provider:
timeout: 1000 # 【重要】远程服务调用超时时间,单位:毫秒。默认为 1000 毫秒,胖友可以根据自己业务修改
UserRpcService:
- version: 1.0.
+ version: 1.0.0
# 配置扫描 Dubbo 自定义的 @Service 注解,暴露成 Dubbo 服务提供者
scan:
base-packages: cn.iocoder.springboot.lab30.rpc.service
diff --git a/lab-52/lab-52-multiple-datasource/pom.xml b/lab-52/lab-52-multiple-datasource/pom.xml
index 412a459eb..69a1990bd 100644
--- a/lab-52/lab-52-multiple-datasource/pom.xml
+++ b/lab-52/lab-52-multiple-datasource/pom.xml
@@ -13,7 +13,7 @@
lab-52-multiple-datasource
-
+
org.springframework.boot
spring-boot-starter-web
@@ -30,7 +30,7 @@
5.1.48
-
+
org.mybatis.spring.boot
mybatis-spring-boot-starter
@@ -44,7 +44,7 @@
3.0.0
-
+
io.seata
seata-spring-boot-starter
diff --git a/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/StorageService.java b/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/ProductService.java
similarity index 85%
rename from lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/StorageService.java
rename to lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/ProductService.java
index b9e07c571..fdba69c2d 100644
--- a/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/StorageService.java
+++ b/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/ProductService.java
@@ -1,9 +1,9 @@
package cn.iocoder.springboot.lab52.seatademo.service;
/**
- * 库存 Service
+ * 商品 Service
*/
-public interface StorageService {
+public interface ProductService {
/**
* 扣减库存
diff --git a/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/AmountServiceImpl.java b/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/AccountServiceImpl.java
similarity index 95%
rename from lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/AmountServiceImpl.java
rename to lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/AccountServiceImpl.java
index 5e8bfda4b..5149eb1f2 100644
--- a/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/AmountServiceImpl.java
+++ b/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/AccountServiceImpl.java
@@ -12,7 +12,7 @@
import org.springframework.transaction.annotation.Transactional;
@Service
-public class AmountServiceImpl implements AccountService {
+public class AccountServiceImpl implements AccountService {
private Logger logger = LoggerFactory.getLogger(getClass());
@@ -20,7 +20,7 @@ public class AmountServiceImpl implements AccountService {
private AccountDao accountDao;
@Override
- @DS(value = "pay-ds")
+ @DS(value = "account-ds")
@Transactional(propagation = Propagation.REQUIRES_NEW) // 开启新事物
public void reduceBalance(Long userId, Integer price) throws Exception {
logger.info("[reduceBalance] 当前 XID: {}", RootContext.getXID());
diff --git a/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/OrderServiceImpl.java b/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/OrderServiceImpl.java
index f8db0b82b..40e67811f 100644
--- a/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/OrderServiceImpl.java
+++ b/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/OrderServiceImpl.java
@@ -4,7 +4,7 @@
import cn.iocoder.springboot.lab52.seatademo.entity.OrderDO;
import cn.iocoder.springboot.lab52.seatademo.service.OrderService;
import cn.iocoder.springboot.lab52.seatademo.service.AccountService;
-import cn.iocoder.springboot.lab52.seatademo.service.StorageService;
+import cn.iocoder.springboot.lab52.seatademo.service.ProductService;
import com.baomidou.dynamic.datasource.annotation.DS;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
@@ -22,10 +22,10 @@ public class OrderServiceImpl implements OrderService {
private OrderDao orderDao;
@Autowired
- private AccountService payService;
+ private AccountService accountService;
@Autowired
- private StorageService storageService;
+ private ProductService productService;
@GlobalTransactional
@Override
@@ -36,10 +36,10 @@ public Integer createOrder(Long userId, Long productId, Integer price) throws Ex
logger.info("[createOrder] 当前 XID: {}", RootContext.getXID());
// 扣减库存
- storageService.reduceStock(productId, amount);
+ productService.reduceStock(productId, amount);
// 扣减余额
- payService.reduceBalance(userId, price);
+ accountService.reduceBalance(userId, price);
// 保存订单
OrderDO order = new OrderDO().setUserId(userId).setProductId(productId).setPayAmount(amount * price);
diff --git a/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/StorageServiceImpl.java b/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/ProductServiceImpl.java
similarity index 85%
rename from lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/StorageServiceImpl.java
rename to lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/ProductServiceImpl.java
index 669d5b050..ac3c27a25 100644
--- a/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/StorageServiceImpl.java
+++ b/lab-52/lab-52-multiple-datasource/src/main/java/cn/iocoder/springboot/lab52/seatademo/service/impl/ProductServiceImpl.java
@@ -1,7 +1,7 @@
package cn.iocoder.springboot.lab52.seatademo.service.impl;
import cn.iocoder.springboot.lab52.seatademo.dao.ProductDao;
-import cn.iocoder.springboot.lab52.seatademo.service.StorageService;
+import cn.iocoder.springboot.lab52.seatademo.service.ProductService;
import com.baomidou.dynamic.datasource.annotation.DS;
import io.seata.core.context.RootContext;
import org.slf4j.Logger;
@@ -12,7 +12,7 @@
import org.springframework.transaction.annotation.Transactional;
@Service
-public class StorageServiceImpl implements StorageService {
+public class ProductServiceImpl implements ProductService {
private Logger logger = LoggerFactory.getLogger(getClass());
@@ -20,7 +20,7 @@ public class StorageServiceImpl implements StorageService {
private ProductDao productDao;
@Override
- @DS(value = "storage-ds")
+ @DS(value = "product-ds")
@Transactional(propagation = Propagation.REQUIRES_NEW) // 开启新事物
public void reduceStock(Long productId, Integer amount) throws Exception {
logger.info("[reduceStock] 当前 XID: {}", RootContext.getXID());
@@ -33,11 +33,11 @@ public void reduceStock(Long productId, Integer amount) throws Exception {
int updateCount = productDao.reduceStock(productId, amount);
// 扣除成功
if (updateCount == 0) {
- logger.warn("[reduceStock] 扣除 {} 库存成功", productId);
+ logger.warn("[reduceStock] 扣除 {} 库存失败", productId);
throw new Exception("库存不足");
}
// 扣除失败
- logger.info("[reduceStock] 扣除 {} 库存失败", productId);
+ logger.info("[reduceStock] 扣除 {} 库存成功", productId);
}
private void checkStock(Long productId, Integer requiredAmount) throws Exception {
diff --git a/lab-52/lab-52-multiple-datasource/src/main/resources/application.yaml b/lab-52/lab-52-multiple-datasource/src/main/resources/application.yaml
index 0a0773d6f..7ce40cebc 100644
--- a/lab-52/lab-52-multiple-datasource/src/main/resources/application.yaml
+++ b/lab-52/lab-52-multiple-datasource/src/main/resources/application.yaml
@@ -17,14 +17,14 @@ spring:
username: root
password:
# 账户 pay 数据源配置
- amount-ds:
- url: jdbc:mysql://127.0.0.1:3306/seata_pay?useSSL=false&useUnicode=true&characterEncoding=UTF-8
+ account-ds:
+ url: jdbc:mysql://127.0.0.1:3306/seata_account?useSSL=false&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
username: root
password:
- # 库存 storage 数据源配置
- storage-ds:
- url: jdbc:mysql://127.0.0.1:3306/seata_storage?useSSL=false&useUnicode=true&characterEncoding=UTF-8
+ # 商品 product 数据源配置
+ product-ds:
+ url: jdbc:mysql://127.0.0.1:3306/seata_product?useSSL=false&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
username: root
password:
diff --git a/lab-52/lab-52-multiple-datasource/src/main/resources/data.sql b/lab-52/lab-52-multiple-datasource/src/main/resources/data.sql
new file mode 100644
index 000000000..422c46f74
--- /dev/null
+++ b/lab-52/lab-52-multiple-datasource/src/main/resources/data.sql
@@ -0,0 +1,83 @@
+# Order
+DROP DATABASE IF EXISTS seata_order;
+CREATE DATABASE seata_order;
+
+CREATE TABLE seata_order.orders
+(
+ id INT(11) NOT NULL AUTO_INCREMENT,
+ user_id INT(11) DEFAULT NULL,
+ product_id INT(11) DEFAULT NULL,
+ pay_amount DECIMAL(10, 0) DEFAULT NULL,
+ add_time DATETIME DEFAULT CURRENT_TIMESTAMP,
+ last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (id)
+) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;
+
+CREATE TABLE seata_order.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;
+
+# Product
+DROP DATABASE IF EXISTS seata_product;
+CREATE DATABASE seata_product;
+
+CREATE TABLE seata_product.product
+(
+ id INT(11) NOT NULL AUTO_INCREMENT,
+ stock INT(11) DEFAULT NULL,
+ last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (id)
+) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;
+INSERT INTO seata_product.product (id, stock) VALUES (1, 10); # 插入一条产品的库存
+
+CREATE TABLE seata_product.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;
+
+# Account
+DROP DATABASE IF EXISTS seata_account;
+CREATE DATABASE seata_account;
+
+CREATE TABLE seata_account.account
+(
+ id INT(11) NOT NULL AUTO_INCREMENT,
+ balance DOUBLE DEFAULT NULL,
+ last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (id)
+) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;
+
+CREATE TABLE seata_account.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;
+INSERT INTO seata_account.account (id, balance) VALUES (1, 10);
+
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/data.sql b/lab-53/lab-53-seata-at-dubbo-demo/data.sql
new file mode 100644
index 000000000..3b0ce0828
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/data.sql
@@ -0,0 +1,82 @@
+# Order
+DROP DATABASE IF EXISTS seata_order;
+CREATE DATABASE seata_order;
+
+CREATE TABLE seata_order.orders
+(
+ id INT(11) NOT NULL AUTO_INCREMENT,
+ user_id INT(11) DEFAULT NULL,
+ product_id INT(11) DEFAULT NULL,
+ pay_amount DECIMAL(10, 0) DEFAULT NULL,
+ add_time DATETIME DEFAULT CURRENT_TIMESTAMP,
+ last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (id)
+) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;
+
+CREATE TABLE seata_order.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;
+
+# Product
+DROP DATABASE IF EXISTS seata_product;
+CREATE DATABASE seata_product;
+
+CREATE TABLE seata_product.product
+(
+ id INT(11) NOT NULL AUTO_INCREMENT,
+ stock INT(11) DEFAULT NULL,
+ last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (id)
+) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;
+INSERT INTO seata_product.product (id, stock) VALUES (1, 10); # 插入一条产品的库存
+
+CREATE TABLE seata_product.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;
+
+# Account
+DROP DATABASE IF EXISTS seata_account;
+CREATE DATABASE seata_account;
+
+CREATE TABLE seata_account.account
+(
+ id INT(11) NOT NULL AUTO_INCREMENT,
+ balance DOUBLE DEFAULT NULL,
+ last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (id)
+) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;
+
+CREATE TABLE seata_account.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;
+INSERT INTO seata_account.account (id, balance) VALUES (1, 10);
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service-api/pom.xml b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service-api/pom.xml
new file mode 100644
index 000000000..f8deb4b0a
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service-api/pom.xml
@@ -0,0 +1,14 @@
+
+
+
+ lab-53-seata-at-dubbo-demo
+ cn.iocoder.springboot.labs
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ lab-53-seata-at-dubbo-demo-account-service-api
+
+
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service-api/src/main/java/cn/iocoder/springboot/lab53/accountservice/api/AccountService.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service-api/src/main/java/cn/iocoder/springboot/lab53/accountservice/api/AccountService.java
new file mode 100644
index 000000000..178aa78ef
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service-api/src/main/java/cn/iocoder/springboot/lab53/accountservice/api/AccountService.java
@@ -0,0 +1,17 @@
+package cn.iocoder.springboot.lab53.accountservice.api;
+
+/**
+ * 账户 Service
+ */
+public interface AccountService {
+
+ /**
+ * 扣除余额
+ *
+ * @param userId 用户编号
+ * @param price 扣减金额
+ * @throws Exception 失败时抛出异常
+ */
+ void reduceBalance(Long userId, Integer price) throws Exception;
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/pom.xml b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/pom.xml
new file mode 100644
index 000000000..f8ee16f95
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/pom.xml
@@ -0,0 +1,73 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.2.RELEASE
+
+
+ 4.0.0
+
+ lab-53-seata-at-dubbo-demo-account-service
+
+
+
+ cn.iocoder.springboot.labs
+ lab-53-seata-at-dubbo-demo-account-service-api
+ 1.0-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ mysql
+ mysql-connector-java
+ 5.1.48
+
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 2.1.2
+
+
+
+
+ io.seata
+ seata-spring-boot-starter
+ 1.1.0
+
+
+
+
+ org.apache.dubbo
+ dubbo
+ 2.7.4.1
+
+
+ org.apache.dubbo
+ dubbo-spring-boot-starter
+ 2.7.4.1
+
+
+
+
+ com.alibaba
+ dubbo-registry-nacos
+ 2.7.6
+
+
+
+
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/java/cn/iocoder/springboot/lab53/accountservice/AccountServiceApplication.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/java/cn/iocoder/springboot/lab53/accountservice/AccountServiceApplication.java
new file mode 100644
index 000000000..91ce94eb1
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/java/cn/iocoder/springboot/lab53/accountservice/AccountServiceApplication.java
@@ -0,0 +1,13 @@
+package cn.iocoder.springboot.lab53.accountservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class AccountServiceApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(AccountServiceApplication.class, args);
+ }
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/java/cn/iocoder/springboot/lab53/accountservice/dao/AccountDao.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/java/cn/iocoder/springboot/lab53/accountservice/dao/AccountDao.java
new file mode 100644
index 000000000..3d800a4e9
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/java/cn/iocoder/springboot/lab53/accountservice/dao/AccountDao.java
@@ -0,0 +1,32 @@
+package cn.iocoder.springboot.lab53.accountservice.dao;
+
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+@Repository
+public interface AccountDao {
+
+ /**
+ * 获取账户余额
+ *
+ * @param userId 用户 ID
+ * @return 账户余额
+ */
+ @Select("SELECT balance FROM account WHERE id = #{userId}")
+ Integer getBalance(@Param("userId") Long userId);
+
+ /**
+ * 扣减余额
+ *
+ * @param price 需要扣减的数目
+ * @return 影响记录行数
+ */
+ @Update("UPDATE account SET balance = balance - #{price} WHERE id = 1 AND balance >= ${price}")
+ int reduceBalance(@Param("price") Integer price);
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/java/cn/iocoder/springboot/lab53/accountservice/service/AccountServiceImpl.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/java/cn/iocoder/springboot/lab53/accountservice/service/AccountServiceImpl.java
new file mode 100644
index 000000000..c5e5cebc8
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/java/cn/iocoder/springboot/lab53/accountservice/service/AccountServiceImpl.java
@@ -0,0 +1,48 @@
+package cn.iocoder.springboot.lab53.accountservice.service;
+
+import cn.iocoder.springboot.lab53.accountservice.api.AccountService;
+import cn.iocoder.springboot.lab53.accountservice.dao.AccountDao;
+import io.seata.core.context.RootContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+@org.apache.dubbo.config.annotation.Service
+public class AccountServiceImpl implements AccountService {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Autowired
+ private AccountDao accountDao;
+
+ @Override
+ @Transactional(propagation = Propagation.REQUIRES_NEW) // 开启新事物
+ public void reduceBalance(Long userId, Integer price) throws Exception {
+ logger.info("[reduceBalance] 当前 XID: {}", RootContext.getXID());
+
+ // 检查余额
+ checkBalance(userId, price);
+
+ logger.info("[reduceBalance] 开始扣减用户 {} 余额", userId);
+ // 扣除余额
+ int updateCount = accountDao.reduceBalance(price);
+ // 扣除成功
+ if (updateCount == 0) {
+ logger.warn("[reduceBalance] 扣除用户 {} 余额失败", userId);
+ throw new Exception("余额不足");
+ }
+ logger.info("[reduceBalance] 扣除用户 {} 余额成功", userId);
+ }
+
+ private void checkBalance(Long userId, Integer price) throws Exception {
+ logger.info("[checkBalance] 检查用户 {} 余额", userId);
+ Integer balance = accountDao.getBalance(userId);
+ if (balance < price) {
+ logger.warn("[checkBalance] 用户 {} 余额不足,当前余额:{}", userId, balance);
+ throw new Exception("余额不足");
+ }
+ }
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/resources/application.yaml b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/resources/application.yaml
new file mode 100644
index 000000000..85d719706
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-account-service/src/main/resources/application.yaml
@@ -0,0 +1,38 @@
+spring:
+ application:
+ name: account-service
+
+ datasource:
+ url: jdbc:mysql://127.0.0.1:3306/seata_account?useSSL=false&useUnicode=true&characterEncoding=UTF-8
+ driver-class-name: com.mysql.jdbc.Driver
+ username: root
+ password:
+
+# dubbo 配置项,对应 DubboConfigurationProperties 配置类
+dubbo:
+ # Dubbo 应用配置
+ application:
+ name: ${spring.application.name} # 应用名
+ # Dubbo 注册中心配
+ registry:
+ address: nacos://127.0.0.1:8848 # 注册中心地址。个鞥多注册中心,可见 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文档。
+ # Dubbo 服务提供者协议配置
+ protocol:
+ port: -1 # 协议端口。使用 -1 表示随机端口。
+ name: dubbo # 使用 `dubbo://` 协议。更多协议,可见 http://dubbo.apache.org/zh-cn/docs/user/references/protocol/introduction.html 文档
+ # 配置扫描 Dubbo 自定义的 @Service 注解,暴露成 Dubbo 服务提供者
+ scan:
+ base-packages: cn.iocoder.springboot.lab53.accountservice.service
+
+# Seata 配置项,对应 SeataProperties 类
+seata:
+ application-id: ${spring.application.name} # Seata 应用编号,默认为 ${spring.application.name}
+ tx-service-group: ${spring.application.name}-group # Seata 事务组编号,用于 TC 集群名
+ # 服务配置项,对应 ServiceProperties 类
+ service:
+ # 虚拟组和分组的映射
+ vgroup-mapping:
+ account-service-group: default
+ # 分组和 Seata 服务的映射
+ grouplist:
+ default: 127.0.0.1:8091
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service-api/pom.xml b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service-api/pom.xml
new file mode 100644
index 000000000..ec9ccab36
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service-api/pom.xml
@@ -0,0 +1,14 @@
+
+
+
+ lab-53-seata-at-dubbo-demo
+ cn.iocoder.springboot.labs
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ lab-53-seata-at-dubbo-demo-order-service-api
+
+
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service-api/src/main/java/cn/iocoder/springboot/lab53/orderservice/api/OrderService.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service-api/src/main/java/cn/iocoder/springboot/lab53/orderservice/api/OrderService.java
new file mode 100644
index 000000000..34cb0eb8b
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service-api/src/main/java/cn/iocoder/springboot/lab53/orderservice/api/OrderService.java
@@ -0,0 +1,19 @@
+package cn.iocoder.springboot.lab53.orderservice.api;
+
+/**
+ * 订单 Service
+ */
+public interface OrderService {
+
+ /**
+ * 创建订单
+ *
+ * @param userId 用户编号
+ * @param productId 产品编号
+ * @param price 价格
+ * @return 订单编号
+ * @throws Exception 创建订单失败,抛出异常
+ */
+ Integer createOrder(Long userId, Long productId, Integer price) throws Exception;
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/pom.xml b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/pom.xml
new file mode 100644
index 000000000..10693d433
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/pom.xml
@@ -0,0 +1,83 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.2.RELEASE
+
+
+ 4.0.0
+
+ lab-53-seata-at-dubbo-demo-order-service
+
+
+
+ cn.iocoder.springboot.labs
+ lab-53-seata-at-dubbo-demo-order-service-api
+ 1.0-SNAPSHOT
+
+
+ cn.iocoder.springboot.labs
+ lab-53-seata-at-dubbo-demo-account-service-api
+ 1.0-SNAPSHOT
+
+
+ cn.iocoder.springboot.labs
+ lab-53-seata-at-dubbo-demo-product-service-api
+ 1.0-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ mysql
+ mysql-connector-java
+ 5.1.48
+
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 2.1.2
+
+
+
+
+ io.seata
+ seata-spring-boot-starter
+ 1.1.0
+
+
+
+
+ org.apache.dubbo
+ dubbo
+ 2.7.4.1
+
+
+ org.apache.dubbo
+ dubbo-spring-boot-starter
+ 2.7.4.1
+
+
+
+
+ com.alibaba
+ dubbo-registry-nacos
+ 2.7.6
+
+
+
+
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/OrderServiceApplication.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/OrderServiceApplication.java
new file mode 100644
index 000000000..bf9b2ddf4
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/OrderServiceApplication.java
@@ -0,0 +1,13 @@
+package cn.iocoder.springboot.lab53.orderservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class OrderServiceApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(OrderServiceApplication.class, args);
+ }
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/controller/OrderController.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/controller/OrderController.java
new file mode 100644
index 000000000..ccbef5c6f
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/controller/OrderController.java
@@ -0,0 +1,29 @@
+package cn.iocoder.springboot.lab53.orderservice.controller;
+
+import cn.iocoder.springboot.lab53.orderservice.api.OrderService;
+import org.apache.dubbo.config.annotation.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/order")
+public class OrderController {
+
+ private Logger logger = LoggerFactory.getLogger(OrderController.class);
+
+ @Reference
+ private OrderService orderService;
+
+ @PostMapping("/create")
+ public Integer createOrder(@RequestParam("userId") Long userId,
+ @RequestParam("productId") Long productId,
+ @RequestParam("price") Integer price) throws Exception {
+ logger.info("[createOrder] 收到下单请求,用户:{}, 商品:{}, 价格:{}", userId, productId, price);
+ return orderService.createOrder(userId, productId, price);
+ }
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/dao/OrderDao.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/dao/OrderDao.java
new file mode 100644
index 000000000..2c0518bf7
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/dao/OrderDao.java
@@ -0,0 +1,23 @@
+package cn.iocoder.springboot.lab53.orderservice.dao;
+
+import cn.iocoder.springboot.lab53.orderservice.entity.OrderDO;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Options;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+@Repository
+public interface OrderDao {
+
+ /**
+ * 插入订单记录
+ *
+ * @param order 订单
+ * @return 影响记录数量
+ */
+ @Insert("INSERT INTO orders (user_id, product_id, pay_amount) VALUES (#{userId}, #{productId}, #{payAmount})")
+ @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
+ int saveOrder(OrderDO order);
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/entity/OrderDO.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/entity/OrderDO.java
new file mode 100644
index 000000000..4ff509e40
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/entity/OrderDO.java
@@ -0,0 +1,56 @@
+package cn.iocoder.springboot.lab53.orderservice.entity;
+
+/**
+ * 订单实体
+ */
+public class OrderDO {
+
+ /** 订单编号 **/
+ private Integer id;
+
+ /** 用户编号 **/
+ private Long userId;
+
+ /** 产品编号 **/
+ private Long productId;
+
+ /** 支付金额 **/
+ private Integer payAmount;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public OrderDO setId(Integer id) {
+ this.id = id;
+ return this;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+
+ public OrderDO setUserId(Long userId) {
+ this.userId = userId;
+ return this;
+ }
+
+ public Long getProductId() {
+ return productId;
+ }
+
+ public OrderDO setProductId(Long productId) {
+ this.productId = productId;
+ return this;
+ }
+
+ public Integer getPayAmount() {
+ return payAmount;
+ }
+
+ public OrderDO setPayAmount(Integer payAmount) {
+ this.payAmount = payAmount;
+ return this;
+ }
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/service/OrderServiceImpl.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/service/OrderServiceImpl.java
new file mode 100644
index 000000000..1a445090d
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/java/cn/iocoder/springboot/lab53/orderservice/service/OrderServiceImpl.java
@@ -0,0 +1,51 @@
+package cn.iocoder.springboot.lab53.orderservice.service;
+
+import cn.iocoder.springboot.lab53.accountservice.api.AccountService;
+import cn.iocoder.springboot.lab53.orderservice.api.OrderService;
+import cn.iocoder.springboot.lab53.orderservice.dao.OrderDao;
+import cn.iocoder.springboot.lab53.orderservice.entity.OrderDO;
+import cn.iocoder.springboot.lab53.storageservice.api.ProductService;
+import io.seata.core.context.RootContext;
+import io.seata.spring.annotation.GlobalTransactional;
+import org.apache.dubbo.config.annotation.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+@org.apache.dubbo.config.annotation.Service
+public class OrderServiceImpl implements OrderService {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Autowired
+ private OrderDao orderDao;
+
+ @Reference
+ private AccountService accountService;
+
+ @Reference
+ private ProductService productService;
+
+ @Override
+ @GlobalTransactional
+ public Integer createOrder(Long userId, Long productId, Integer price) throws Exception {
+ Integer amount = 1; // 购买数量,暂时设置为 1。
+
+ logger.info("[createOrder] 当前 XID: {}", RootContext.getXID());
+
+ // 扣减库存
+ productService.reduceStock(productId, amount);
+
+ // 扣减余额
+ accountService.reduceBalance(userId, price);
+
+ // 保存订单
+ OrderDO order = new OrderDO().setUserId(userId).setProductId(productId).setPayAmount(amount * price);
+ orderDao.saveOrder(order);
+ logger.info("[createOrder] 保存订单: {}", order.getId());
+
+ // 返回订单编号
+ return order.getId();
+ }
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/resources/application.yaml b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/resources/application.yaml
new file mode 100644
index 000000000..81773e6cd
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-order-service/src/main/resources/application.yaml
@@ -0,0 +1,41 @@
+server:
+ port: 8081 # 端口
+
+spring:
+ application:
+ name: user-service
+
+ datasource:
+ url: jdbc:mysql://127.0.0.1:3306/seata_order?useSSL=false&useUnicode=true&characterEncoding=UTF-8
+ driver-class-name: com.mysql.jdbc.Driver
+ username: root
+ password:
+
+# dubbo 配置项,对应 DubboConfigurationProperties 配置类
+dubbo:
+ # Dubbo 应用配置
+ application:
+ name: ${spring.application.name} # 应用名
+ # Dubbo 注册中心配
+ registry:
+ address: nacos://127.0.0.1:8848 # 注册中心地址。个鞥多注册中心,可见 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文档。
+ # Dubbo 服务提供者协议配置
+ protocol:
+ port: -1 # 协议端口。使用 -1 表示随机端口。
+ name: dubbo # 使用 `dubbo://` 协议。更多协议,可见 http://dubbo.apache.org/zh-cn/docs/user/references/protocol/introduction.html 文档
+ # 配置扫描 Dubbo 自定义的 @Service 注解,暴露成 Dubbo 服务提供者
+ scan:
+ base-packages: cn.iocoder.springboot.lab53.orderservice.service
+
+# Seata 配置项,对应 SeataProperties 类
+seata:
+ application-id: ${spring.application.name} # Seata 应用编号,默认为 ${spring.application.name}
+ tx-service-group: ${spring.application.name}-group # Seata 事务组编号,用于 TC 集群名
+ # 服务配置项,对应 ServiceProperties 类
+ service:
+ # 虚拟组和分组的映射
+ vgroup-mapping:
+ user-service-group: default
+ # 分组和 Seata 服务的映射
+ grouplist:
+ default: 127.0.0.1:8091
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service-api/pom.xml b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service-api/pom.xml
new file mode 100644
index 000000000..d242cb725
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service-api/pom.xml
@@ -0,0 +1,14 @@
+
+
+
+ lab-53-seata-at-dubbo-demo
+ cn.iocoder.springboot.labs
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ lab-53-seata-at-dubbo-demo-product-service-api
+
+
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service-api/src/main/java/cn/iocoder/springboot/lab53/storageservice/api/ProductService.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service-api/src/main/java/cn/iocoder/springboot/lab53/storageservice/api/ProductService.java
new file mode 100644
index 000000000..01e069092
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service-api/src/main/java/cn/iocoder/springboot/lab53/storageservice/api/ProductService.java
@@ -0,0 +1,17 @@
+package cn.iocoder.springboot.lab53.storageservice.api;
+
+/**
+ * 商品 Service
+ */
+public interface ProductService {
+
+ /**
+ * 扣减库存
+ *
+ * @param productId 商品 ID
+ * @param amount 扣减数量
+ * @throws Exception 扣减失败时抛出异常
+ */
+ void reduceStock(Long productId, Integer amount) throws Exception;
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/pom.xml b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/pom.xml
new file mode 100644
index 000000000..73ee3dcbe
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/pom.xml
@@ -0,0 +1,73 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.2.RELEASE
+
+
+ 4.0.0
+
+ lab-53-seata-at-dubbo-demo-product-service
+
+
+
+ cn.iocoder.springboot.labs
+ lab-53-seata-at-dubbo-demo-product-service-api
+ 1.0-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ mysql
+ mysql-connector-java
+ 5.1.48
+
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 2.1.2
+
+
+
+
+ io.seata
+ seata-spring-boot-starter
+ 1.1.0
+
+
+
+
+ org.apache.dubbo
+ dubbo
+ 2.7.4.1
+
+
+ org.apache.dubbo
+ dubbo-spring-boot-starter
+ 2.7.4.1
+
+
+
+
+ com.alibaba
+ dubbo-registry-nacos
+ 2.7.6
+
+
+
+
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/java/cn/iocoder/springboot/lab53/productservice/ProductServiceApplication.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/java/cn/iocoder/springboot/lab53/productservice/ProductServiceApplication.java
new file mode 100644
index 000000000..0f286bb1c
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/java/cn/iocoder/springboot/lab53/productservice/ProductServiceApplication.java
@@ -0,0 +1,13 @@
+package cn.iocoder.springboot.lab53.productservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ProductServiceApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ProductServiceApplication.class, args);
+ }
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/java/cn/iocoder/springboot/lab53/productservice/dao/ProductDao.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/java/cn/iocoder/springboot/lab53/productservice/dao/ProductDao.java
new file mode 100644
index 000000000..df404727c
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/java/cn/iocoder/springboot/lab53/productservice/dao/ProductDao.java
@@ -0,0 +1,33 @@
+package cn.iocoder.springboot.lab53.productservice.dao;
+
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+@Repository
+public interface ProductDao {
+
+ /**
+ * 获取库存
+ *
+ * @param productId 商品编号
+ * @return 库存
+ */
+ @Select("SELECT stock FROM product WHERE id = #{productId}")
+ Integer getStock(@Param("productId") Long productId);
+
+ /**
+ * 扣减库存
+ *
+ * @param productId 商品编号
+ * @param amount 扣减数量
+ * @return 影响记录行数
+ */
+ @Update("UPDATE product SET stock = stock - #{amount} WHERE id = #{productId} AND stock >= #{amount}")
+ int reduceStock(@Param("productId") Long productId, @Param("amount") Integer amount);
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/java/cn/iocoder/springboot/lab53/productservice/service/ProductService.java b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/java/cn/iocoder/springboot/lab53/productservice/service/ProductService.java
new file mode 100644
index 000000000..e03a6cdf0
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/java/cn/iocoder/springboot/lab53/productservice/service/ProductService.java
@@ -0,0 +1,17 @@
+package cn.iocoder.springboot.lab53.productservice.service;
+
+/**
+ * 商品 Service
+ */
+public interface ProductService {
+
+ /**
+ * 扣减库存
+ *
+ * @param productId 商品 ID
+ * @param amount 扣减数量
+ * @throws Exception 扣减失败时抛出异常
+ */
+ void reduceStock(Long productId, Integer amount) throws Exception;
+
+}
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/resources/application.yaml b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/resources/application.yaml
new file mode 100644
index 000000000..63068ae2f
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/lab-53-seata-at-dubbo-demo-product-service/src/main/resources/application.yaml
@@ -0,0 +1,38 @@
+spring:
+ application:
+ name: product-service
+
+ datasource:
+ url: jdbc:mysql://127.0.0.1:3306/seata_product?useSSL=false&useUnicode=true&characterEncoding=UTF-8
+ driver-class-name: com.mysql.jdbc.Driver
+ username: root
+ password:
+
+# dubbo 配置项,对应 DubboConfigurationProperties 配置类
+dubbo:
+ # Dubbo 应用配置
+ application:
+ name: ${spring.application.name} # 应用名
+ # Dubbo 注册中心配
+ registry:
+ address: nacos://127.0.0.1:8848 # 注册中心地址。个鞥多注册中心,可见 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文档。
+ # Dubbo 服务提供者协议配置
+ protocol:
+ port: -1 # 协议端口。使用 -1 表示随机端口。
+ name: dubbo # 使用 `dubbo://` 协议。更多协议,可见 http://dubbo.apache.org/zh-cn/docs/user/references/protocol/introduction.html 文档
+ # 配置扫描 Dubbo 自定义的 @Service 注解,暴露成 Dubbo 服务提供者
+ scan:
+ base-packages: cn.iocoder.springboot.lab53.productservice.service
+
+# Seata 配置项,对应 SeataProperties 类
+seata:
+ application-id: ${spring.application.name} # Seata 应用编号,默认为 ${spring.application.name}
+ tx-service-group: ${spring.application.name}-group # Seata 事务组编号,用于 TC 集群名
+ # 服务配置项,对应 ServiceProperties 类
+ service:
+ # 虚拟组和分组的映射
+ vgroup-mapping:
+ product-service-group: default
+ # 分组和 Seata 服务的映射
+ grouplist:
+ default: 127.0.0.1:8091
diff --git a/lab-53/lab-53-seata-at-dubbo-demo/pom.xml b/lab-53/lab-53-seata-at-dubbo-demo/pom.xml
new file mode 100644
index 000000000..e31344ded
--- /dev/null
+++ b/lab-53/lab-53-seata-at-dubbo-demo/pom.xml
@@ -0,0 +1,24 @@
+
+
+
+ lab-53
+ cn.iocoder.springboot.labs
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ lab-53-seata-at-dubbo-demo
+ pom
+
+
+ lab-53-seata-at-dubbo-demo-order-service-api
+ lab-53-seata-at-dubbo-demo-order-service
+ lab-53-seata-at-dubbo-demo-account-service-api
+ lab-53-seata-at-dubbo-demo-account-service
+ lab-53-seata-at-dubbo-demo-product-service-api
+ lab-53-seata-at-dubbo-demo-product-service
+
+
+
diff --git a/lab-53/pom.xml b/lab-53/pom.xml
new file mode 100644
index 000000000..6148e803f
--- /dev/null
+++ b/lab-53/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ labs-parent
+ cn.iocoder.springboot.labs
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ lab-53
+ pom
+
+
+ lab-53-seata-at-dubbo-demo
+
+
+
+
diff --git a/pom.xml b/pom.xml
index aa31dfe8e..8fead4153 100644
--- a/pom.xml
+++ b/pom.xml
@@ -80,6 +80,7 @@
labx-15
labx-16
lab-52
+ lab-53