seata案例之springcloud+MybatisPlus+nacos+seata

seata案例之springcloud+MybatisPlus+nacos+seata

源码

https://gitee.com/tong-exists/springcloud-MybatisPlus-nacos-seata

1 版本

springboot、springcloud、springcloudalibaba、nacos-server、seata-server的版本需要谨慎选择,选择能够兼容的版本。具体参考https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

本项目使用的版本

springboot2.6.3
springcloud2021.0.1
springcloudalibaba2021.0.1.0
nacos-server1.4.2
seata-server1.4.2

2 搭建springboot+MybatisPlus

2.1业务

用户购买商品的业务逻辑。整个业务逻辑由3个微服务提供支持:

仓储服务:对给定的商品扣除仓储数量。

订单服务:根据采购需求创建订单。

帐户服务:从用户帐户中扣除余额。

在这里插入图片描述

2.2数据库表

创建三个数据库account_db、order_db、storage_db

account_db

DROP TABLE IF EXISTS `t_account`;

CREATE TABLE `t_account` (

 `id` int NOT NULL AUTO_INCREMENT,

 `user_id` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `money` int NULL DEFAULT 0,

 PRIMARY KEY (`id`) USING BTREE

) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;

order_db

DROP TABLE IF EXISTS `t_order`;

CREATE TABLE `t_order` (

 `id` int NOT NULL AUTO_INCREMENT,

 `user_id` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `commodity_code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `count` int NULL DEFAULT 0,

 `money` int NULL DEFAULT 0,

 PRIMARY KEY (`id`) USING BTREE

) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;

storage_db

DROP TABLE IF EXISTS `t_storage`;

CREATE TABLE `t_storage` (

 `id` int NOT NULL AUTO_INCREMENT,

 `commodity_code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `count` int NULL DEFAULT 0,

 PRIMARY KEY (`id`) USING BTREE,

 UNIQUE INDEX `commodity_code`(`commodity_code`) USING BTREE

) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;

 

2.3项目整体架构

在这里插入图片描述

2.4基本依赖

2.4.1 seata-learn pom

父项目引入

  • spring-boot-starter-web、spring-boot-starter-actuator、spring-boot-starter-test构建springboot项目

  • lomok有便利的注解

  • mysql-connector-java mysql依赖

  • mybatis-plus-boot-starter mybatisPlus依赖

  • mybatis-plus-generator、freemarker用于代码生成

<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.6.3</version>
   <relativePath/> <!-- lookup parent from repository -->
 </parent>

<dependencies>

    <dependency>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    <dependency>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-actuator</artifactId>

    </dependency>

    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->

    <dependency>

      <groupId>mysql</groupId>

      <artifactId>mysql-connector-java</artifactId>

      <version>8.0.11</version>

      <scope>runtime</scope>

    </dependency>

    <dependency>

      <groupId>org.projectlombok</groupId>

      <artifactId>lombok</artifactId>

      <optional>true</optional>

    </dependency>

    <dependency>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-test</artifactId>

      <scope>test</scope>

    </dependency>

    <dependency>

      <groupId>com.baomidou</groupId>

      <artifactId>mybatis-plus-boot-starter</artifactId>

      <version>3.5.2</version>

    </dependency>

    <dependency>

      <groupId>com.baomidou</groupId>

      <artifactId>mybatis-plus-generator</artifactId>

      <version>3.5.2</version>

      <scope>test</scope>

    </dependency>

    <!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->

    <dependency>

      <groupId>org.freemarker</groupId>

      <artifactId>freemarker</artifactId>

      <version>2.3.31</version>

      <scope>test</scope>

    </dependency>

</dependencies>

2.4.2 storage pom…

storage pom、order pom、account pom 、business pom都是这样

<parent>
    <artifactId>seata-learn</artifactId>
    <groupId>com.example</groupId>
    <version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>common</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

2.4.3 common pom

无依赖

<parent>
   <artifactId>seata-learn</artifactId>
   <groupId>com.example</groupId>
   <version>0.0.1-SNAPSHOT</version>
 </parent>

2.5代码生成

分别将数据库url更改为三个数据库中的一个,修改输出目录,执行main方法,因此要执行三次。生成的代码需要整理到项目中。

public class MybatisPlusGenerateCode {
 
   public static void main(String[] args) {
     FastAutoGenerator.create("jdbc:mysql://localhost:3306/storage_db", "root", "root")
         .globalConfig(builder -> {
           builder.author("tong-exists") // 设置作者
               .fileOverride() // 覆盖已生成文件
               .outputDir("D:\\projects\\spring-cloud-projects\\seata-learn"); // 指定输出目录
         })
         .packageConfig(builder -> {
           builder.parent("com.hello.tong") // 设置父包名
               // 设置父包模块名
               .pathInfo(Collections.singletonMap(OutputFile.xml, "D:\\projects\\spring-cloud-projects\\seata-learn")); // 设置mapperXml生成路径
         })
         .strategyConfig(builder -> {
           builder // 设置需要生成的表名
               .addTablePrefix("t_", "c_"); // 设置过滤表前缀
         })
         .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
         .execute();
   }
 
 }

2.6yml

对于account、order、storage、business根据模块修改下面的代码。例如order模块,修改account-service为order-service,account_db修改为order-db。不同模块的端口需要不一样。

spring:
  datasource:
   url: jdbc:mysql://localhost:3306/account_db?serverTimezone=Asia/Shanghai
   username: root
   password: root
   driver-class-name: com.mysql.cj.jdbc.Driver
  application:
   name: account-service

server:

 port: 8080

2.7启动类

对于account、order、storage、business根据模块修改代码

@SpringBootApplication
 @MapperScan("com.hello.tong.mapper")
 public class AccountApp {
 
   public static void main(String[] args) {
     SpringApplication.run(AccountApp.class);
   }
 
 }

2.8业务代码

其中OrderService、BusinessService的实现类暂未给出,因为涉及到feign服务,而我们尚未引入feign

2.8.1 StorageService

public interface IStorageService extends IService<Storage> {
   /**
   * 扣除存储数量
   */
   void deduct(String commodityCode, int count);
 }

 

@Service

@Slf4j

public class StorageServiceImpl extends ServiceImpl<StorageMapper, Storage> implements IStorageService {

 

  @Autowired

  private StorageMapper storageMapper;

 

  @Override

  public void deduct(String commodityCode, int count) {

     log.info("deduct...");

    storageMapper.updateCountByCommodityCodeInt(commodityCode, count);

  }

}

2.8.2 OrderService

public interface IOrderService extends IService<Order> {
   /**
   * 创建订单
   */
   Order create(String userId, String commodityCode, int orderCount);
 }

2.8.3 AccountService

public interface IAccountService extends IService<Account> {
   /**
   * 从用户账户中借出
   */
   void debit(String userId, int money);
 }

 

@Service

@Slf4j

public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements IAccountService {

 

  @Autowired

  private AccountMapper accountMapper;

 

  @Override

  public void debit(String userId, int money) {

    log.info("debit...");

    accountMapper.updateMoneyByUserId(userId, money);

  }

}

2.8.4 BusinessService

public interface IBusinessService {
 
   public void purchase(String userId, String commodityCode, int orderCount);
 }

3 集成nacos服务发现

3.1启动nacos

cmd窗口执行nacos\bin\startup.cmd -m standalone启动nacos

访问nacos控制台localhost:8848/nacos/index.html,默认账号/密码nacos/nacos

3.2依赖

seata-learn pom

springcloud和springcloudalibaba的版本控制,引入nacos依赖

  <dependencyManagement>

    <dependencies>

      <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->

      <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-dependencies</artifactId>

        <version>2021.0.1</version>

        <type>pom</type>

        <scope>import</scope>

      </dependency>

 

      <dependency>

        <groupId>com.alibaba.cloud</groupId>

        <artifactId>spring-cloud-alibaba-dependencies</artifactId>

        <version>2021.0.1.0</version>

        <type>pom</type>

        <scope>import</scope>

      </dependency>

     </dependencies>

</dependencyManagement>

    <dependencies>

    <dependency>

      <groupId>com.alibaba.cloud</groupId>

      <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>

    </dependency>

     </dependencies>


3.3注解

启动类上加上@EnableDiscoveryClient

@SpringBootApplication
 @MapperScan("com.hello.tong.mapper")
 @EnableDiscoveryClient
 public class StorageApp {
 
   public static void main(String[] args) {
     SpringApplication.run(StorageApp.class);
   }
 
 }

 

3.4yml配置

增加以下配置

spring:
  cloud:
   nacos:
    discovery:
     server-addr: 127.0.0.1:8848
 
 management:
  endpoints:
   web:
    exposure:
     include: "*"

 

4 集成openFeign

4.1依赖

seata-learn pom

   <dependency>

      <groupId>org.springframework.cloud</groupId>

      <artifactId>spring-cloud-starter-loadbalancer</artifactId>

    </dependency>

 

    <dependency>

      <groupId>org.springframework.cloud</groupId>

      <artifactId>spring-cloud-starter-openfeign</artifactId>

    </dependency>

4.2注解

启动类上增加@EnableFeignClients

@SpringBootApplication
 @MapperScan("com.hello.tong.mapper")
 @EnableDiscoveryClient
 @EnableFeignClients
 public class StorageApp {
 
   public static void main(String[] args) {
     SpringApplication.run(StorageApp.class);
   }
 
 }

4.3service

BusinessServiceImpl

@Service
 public class BusinessServiceImpl implements IBusinessService {
   @Autowired
   private StorageFeignService storageService;
   @Autowired
   private OrderFeignService orderService;
 
   /**
   * 采购
   */
   @Override
   public void purchase(String userId, String commodityCode, int orderCount) {
 
     storageService.deduct(commodityCode, orderCount);
 
     orderService.create(userId, commodityCode, orderCount);
   }
 }

OrderServiceImpl

@Service

@Slf4j

public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

 

  @Autowired

  private OrderMapper orderMapper;

 

  @Autowired

  private AccountFeignService accountService;

 

  @Override

  public Order create(String userId, String commodityCode, int orderCount) {

    log.info("create...");

    int orerMoney = calcOrderMoney( commodityCode, orderCount);

    accountService.debit(userId, orerMoney);

    Order order = new Order();

    order.setUserId(userId);

    order.setCommodityCode(commodityCode);

    order.setCount(orderCount);

    order.setMoney(orerMoney);

    orderMapper.insert(order);

    return order;

  }

 

  private int calcOrderMoney(String commodityCode, int orderCount) {

    return orderCount;

  }

}

4.4controller

AccountController

@RestController
 public class AccountController {
 
   @Autowired
   private IAccountService accountService;
 
   @PostMapping("/debit/{userId}/{money}")
 //  @GlobalTransactional
   public void debit(@PathVariable("userId") String userId, @PathVariable("money") int money) {
     accountService.debit(userId, money);
   }
 
 }

BusinessController

@RestController

public class BusinessController {

 

  @Autowired

  private IBusinessService businessService;

 

  @PostMapping("/purchase/{userId}/{commodityCode}/{orderCount}")

//  @GlobalTransactional

  public void purchase(@PathVariable("userId") String userId,

             @PathVariable("commodityCode") String commodityCode,

             @PathVariable("orderCount") int orderCount) {

    businessService.purchase(userId, commodityCode, orderCount);

  }

 

}

OrderController

@RestController

public class OrderController {

 

  @Autowired

  private IOrderService orderService;

 

  @PostMapping("/create/{userId}/{commodityCode}/{orderCount}")

//  @GlobalTransactional

  public Order create(@PathVariable("userId") String userId,

            @PathVariable("commodityCode") String commodityCode,

            @PathVariable("orderCount")int orderCount) {

    return orderService.create(userId, commodityCode, orderCount);

  }

 

}

StorageController

@RestController

public class StorageController {

 

  @Autowired

  private IStorageService storageService;

 

  @PostMapping("/deduct/{commodityCode}/{count}")

//  @GlobalTransactional

  public void deduct(@PathVariable("commodityCode") String commodityCode,@PathVariable("count") int count) {

    storageService.deduct(commodityCode, count);

  }

 

}

4.5feign服务接口

在common模块中编写feign服务接口

AccountFeignService

@FeignClient("account-service")

public interface AccountFeignService {

 

  @PostMapping("/debit/{userId}/{money}")

  public void debit(@PathVariable("userId") String userId, @PathVariable("money") int money);

}

OrderFeignService

@FeignClient("order-service")

public interface OrderFeignService {

 

 

  @PostMapping("/create/{userId}/{commodityCode}/{orderCount}")

  public Order create(@PathVariable("userId") String userId,

            @PathVariable("commodityCode") String commodityCode,

            @PathVariable("orderCount")int orderCount) ;

 

}

StorageFeignService

@FeignClient("storage-service")

public interface StorageFeignService {

 

  @PostMapping("/deduct/{commodityCode}/{count}")

  public void deduct(@PathVariable("commodityCode") String commodityCode, @PathVariable("count") int count) ;

 

}

5 集成seata

5.1seata相关数据库表

seata_db,seata-server用来存储事务信息的数据库

SET NAMES utf8mb4;

SET FOREIGN_KEY_CHECKS = 0;

 

-- ----------------------------

-- Table structure for branch_table

-- ----------------------------

DROP TABLE IF EXISTS `branch_table`;

CREATE TABLE `branch_table` (

 `branch_id` bigint NOT NULL,

 `xid` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,

 `transaction_id` bigint NULL DEFAULT NULL,

 `resource_group_id` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `resource_id` varchar(256) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `branch_type` varchar(8) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `status` tinyint NULL DEFAULT NULL,

 `client_id` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `application_data` varchar(2000) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `gmt_create` datetime(6) NULL DEFAULT NULL,

 `gmt_modified` datetime(6) NULL DEFAULT NULL,

 PRIMARY KEY (`branch_id`) USING BTREE,

 INDEX `idx_xid`(`xid`) USING BTREE

) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;

 

-- ----------------------------

-- Table structure for global_table

-- ----------------------------

DROP TABLE IF EXISTS `global_table`;

CREATE TABLE `global_table` (

 `xid` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,

 `transaction_id` bigint NULL DEFAULT NULL,

 `status` tinyint NOT NULL,

 `application_id` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `transaction_service_group` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `transaction_name` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `timeout` int NULL DEFAULT NULL,

 `begin_time` bigint NULL DEFAULT NULL,

 `application_data` varchar(2000) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `gmt_create` datetime NULL DEFAULT NULL,

 `gmt_modified` datetime NULL DEFAULT NULL,

 PRIMARY KEY (`xid`) USING BTREE,

 INDEX `idx_gmt_modified_status`(`gmt_modified`, `status`) USING BTREE,

 INDEX `idx_transaction_id`(`transaction_id`) USING BTREE

) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;

 

-- ----------------------------

-- Table structure for lock_table

-- ----------------------------

DROP TABLE IF EXISTS `lock_table`;

CREATE TABLE `lock_table` (

 `row_key` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,

 `xid` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `transaction_id` bigint NULL DEFAULT NULL,

 `branch_id` bigint NOT NULL,

 `resource_id` varchar(256) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `table_name` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `pk` varchar(36) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,

 `gmt_create` datetime NULL DEFAULT NULL,

 `gmt_modified` datetime NULL DEFAULT NULL,

 PRIMARY KEY (`row_key`) USING BTREE,

 INDEX `idx_branch_id`(`branch_id`) USING BTREE

) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;

 

SET FOREIGN_KEY_CHECKS = 1;

每个业务数据库都需要增加undo_log表,这个表只在seata使用AT模式时需要

在account_db、order_db、storage_db增加

DROP TABLE IF EXISTS `undo_log`;

CREATE TABLE `undo_log` (

 `branch_id` bigint NOT NULL COMMENT 'branch transaction id',

 `xid` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 'global transaction id',

 `context` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 'undo_log context,such as serialization',

 `rollback_info` longblob NOT NULL COMMENT 'rollback info',

 `log_status` int NOT NULL COMMENT '0:normal status,1:defense status',

 `log_created` datetime(6) NOT NULL COMMENT 'create datetime',

 `log_modified` datetime(6) NOT NULL COMMENT 'modify datetime',

 UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE

) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = 'AT transaction mode undo table' ROW_FORMAT = Dynamic;

5.2启动seata-server

5.2.1 file模式

registry、config使用file模式简化使用

5.2.1.1 配置

registry.conf

registry {

 # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa

 type = "file"

 file {

  name = "file.conf"

 }

}

 

config {

 # file、nacos 、apollo、zk、consul、etcd3

 type = "file"

 file {

  name = "file.conf"

 }

}

file.conf

store模式使用db,将事务信息存储到数据库

## transaction log store, only used in seata-server

store {

 ## store mode: file、db、redis

 mode = "db"

 ## rsa decryption public key

 publicKey = ""

 ## file store property

 

 

 ## database store property

 db {

  ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.

  datasource = "druid"

  ## mysql/oracle/postgresql/h2/oceanbase etc.

  dbType = "mysql"

  driverClassName = "com.mysql.cj.jdbc.Driver"

  ## if using mysql to store the data, recommend add rewriteBatchedStatements=true in jdbc connection param

  url = "jdbc:mysql://127.0.0.1:3306/seata_db?rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai"

  user = "root"

  password = "root"

  minConn = 5

  maxConn = 100

  globalTable = "global_table"

  branchTable = "branch_table"

  lockTable = "lock_table"

  queryLimit = 100

  maxWait = 5000

 }

 

 

}

5.2.2 启动命令

seata-server.bat -h 127.0.0.1 -p 8091 -m db -n 1

5.3依赖

seata-learn pom

<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
        </exclusion>
    </exclusions>
</dependency> 

5.4client配置

5.4.1 file模式

对于account、storage、order、business模块

5.4.1.1 yml
seata:

 data-source-proxy-mode: XA

 registry:

  type: file

 config:

  type: file

 tx-service-group: my_tx_service_group
5.4.1.2 file.conf、registry.conf

resources下增加file.conf、registry.conf

registry.conf

registry {

 # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa

 type = "file"

 

 

 file {

  name = "file.conf"

 }

}

 

config {

 # file、nacos 、apollo、zk、consul、etcd3

 type = "file"

 

 

 file {

  name = "file.conf"

 }

}

file.conf

service {

 vgroupMapping.my_tx_service_group = "cluster1"

 cluster1.grouplist = "127.0.0.1:8091"

}

5.5使用@GlobalTransactional

在需要使用分布式事务的方法上增加@GlobalTransactional

@RestController
 public class BusinessController {
 
   @Autowired
   private IBusinessService businessService;
 
   @PostMapping("/purchase/{userId}/{commodityCode}/{orderCount}")
   @GlobalTransactional
   public void purchase(@PathVariable("userId") String userId,
             @PathVariable("commodityCode") String commodityCode,
             @PathVariable("orderCount") int orderCount) {
     businessService.purchase(userId, commodityCode, orderCount);
   }
 
 }

模拟异常

在OrderService的实现类的create方法手动制造算数异常

public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

 

 

  @Override

  public Order create(String userId, String commodityCode, int orderCount) {

    int a = 3 / 0;

    …

  }

 

  

}

观察@GlobalTransactional有和没有时的区别

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
基于springcloud+springboot+nacos+openFeign的分布式事务组件seata项目源码.zip 介绍 分布式事务组件seata的使用demo,AT模式、TCC模式,集成springboot、springcloudnacos注册中心、openFeign服务调用、Ribbon负载均衡器)、spring jpa,数据库采用mysql demo中使用的相关版本号,具体请看代码。如果搭建个人demo不成功,验证是否是由版本导致,版本稍有变化可能出现相关组件的版本不一致便会出现许多奇怪问题 seata服务端 1.3 Nacos服务端 1.1.4 spring-cloud-alibaba-dependencies 2.1.0.RELEASE springboot 2.1.3.RELEASE springcloud Greenwich.RELEASE 软件架构 软件架构说明 springcloud-common 公共模块 springcloud-order-AT 订单服务 springcloud-product-AT 商品库存服务 springcloud-consumer-AT 消费调用者 springcloud-business-Tcc 工商银行服务 springcloud-merchants-Tcc 招商银行服务 springcloud-Pay-Tcc 消费调用者 AT模式:springcloud-order-AT,springcloud-product-AT,springcloud-consumer-AT为AT模式Dome;模拟场景用户购买商品下单; 调用流程springcloud-consumer-AT调用订单服务创建订单(新增一条数据到订单表);在调用商品库存服务扣减商品库存数量(修改商品库存表商品数量);最后出现异常则统一回滚,负责统一提交; 第一阶段:准备阶段(prepare)协调者通知参与者准备提交订单,参与者开始投票。协调者完成准备工作向协调者回应Yes。 第二阶段:提交(commit)/回滚(rollback)阶段协调者根据参与者的投票结果发起最终的提交指令。如果有参与者没有准备好则发起回滚指令。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值