所得税 网站建设费,建工网论坛,网站建设涉及到哪些方面,网络营销外包公司哪家好前言
上篇文章我们讲述了如何启动seata的本地服务#xff0c;并且注册到nacos使用#xff0c;这篇文章将在SpringCloud中整合Seata框架
上篇文章传送门#xff1a;https://blog.csdn.net/Syals/article/details/130102851?spm1001.2014.3001.5501
本篇主要内容#xff…前言
上篇文章我们讲述了如何启动seata的本地服务并且注册到nacos使用这篇文章将在SpringCloud中整合Seata框架
上篇文章传送门https://blog.csdn.net/Syals/article/details/130102851?spm1001.2014.3001.5501
本篇主要内容GlobalTransactional注解 GlobalTransactional是Seata框架提供的注解用于开启一个全局事务。当一个方法被标记为GlobalTransactional时Seata框架会自动创建一个全局事务并将该方法的执行视为整个事务的一个参与者。 在使用GlobalTransactional注解时需要在Seata Server中配置好相应的事务组并使用相同的事务组ID和事务模式。同时所有参与该全局事务的服务都需要使用相同的事务组ID和事务模式并在业务代码中使用Transactional注解开启本地事务。 当全局事务中的任何一个本地事务发生异常时Seata框架会回滚整个全局事务保证数据的一致性。同时Seata框架还提供了一系列的扩展点和机制可以自定义全局事务的创建、提交和回滚过程以满足不同场景的需求。 使用GlobalTransactional注解可以简化分布式事务的管理和操作提高开发效率和数据一致性。
版本
项版本号jdk1.8SpringBoot2.3.12.RELEASESpringCloud2.2.7.RELEASESpringCloudVersionHoxton.SR12
准备工作 创建一个新的数据库seata-test创建数据库表it_order、it_stock、undo_log 其中it_order是我们的订单表it_stock为库存表undo_log则为seata框架要求的事务日志表在你每个要操作事务的数据库中都要有一个undo_log表 这里的话数据表随便也可以我现在就按演示的数据表来进行操作但是undo_log表是固定的
undo_log表
-- ----------------------------
-- Table structure for undo_log
-- ----------------------------
DROP TABLE IF EXISTS undo_log;
CREATE TABLE undo_log (id bigint(0) NOT NULL AUTO_INCREMENT,branch_id bigint(0) NOT NULL,xid varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,context varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,rollback_info longblob NOT NULL,log_status int(0) NOT NULL,log_created datetime(0) NOT NULL,log_modified datetime(0) NOT NULL,ext varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,PRIMARY KEY (id) USING BTREE,UNIQUE INDEX ux_undo_log(xid, branch_id) USING BTREE
) ENGINE InnoDB AUTO_INCREMENT 1 CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci ROW_FORMAT Dynamic;SET FOREIGN_KEY_CHECKS 1;订单和库存表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS 0;-- ----------------------------
-- Table structure for it_order
-- ----------------------------
DROP TABLE IF EXISTS it_order;
CREATE TABLE it_order (id bigint(0) NOT NULL AUTO_INCREMENT,order_name varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,order_status char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci ROW_FORMAT Dynamic;-- ----------------------------
-- Table structure for it_stock
-- ----------------------------
DROP TABLE IF EXISTS it_stock;
CREATE TABLE it_stock (id bigint(0) NOT NULL AUTO_INCREMENT,order_id bigint(0) NULL DEFAULT NULL,repertory int(0) NULL DEFAULT NULL COMMENT 库存,sales int(0) NULL DEFAULT NULL COMMENT 销量,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci ROW_FORMAT Dynamic;
工程结构图 依赖项说明
父级pom.xml propertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetjava.version1.8/java.versionspring.cloud.alibaba.version2.2.7.RELEASE/spring.cloud.alibaba.versionspring.boot.version2.3.12.RELEASE/spring.boot.versionspring.cloud.versionHoxton.SR12/spring.cloud.version/propertiesdependencies!--SpringBoot基本场景启动--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependency!--SpringBoot 测试的场景启动--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scopeexclusionsexclusiongroupIdorg.junit.vintage/groupIdartifactIdjunit-vintage-engine/artifactId/exclusion/exclusions/dependency/dependenciesdependencyManagement!--Spring Cloud alibaba的版本管理 通过dependency完成继承--dependenciesdependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion${spring.cloud.alibaba.version}/versiontypepom/typescopeimport/scope/dependency!--SpringBoot的版本管理--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion${spring.boot.version}/versiontypepom/typescopeimport/scope/dependency!--Spring Cloud的版本管理--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversion${spring.cloud.version}/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagement2 子级别pom.xml
一些常用的依赖项例如mysql的驱动、web启动器、Druid、Mybaits框架等等。
3 孙级别pom.xml
order和stock的pom文件都是这三个 dependencies!--nacos-服务注册发现--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency!--seata的依赖--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactId/dependency!--1. openfeign依赖 --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependency/dependencies先来配置Order模块的配置文件 stock服务的配置文件我们就不在展示了将下面配置文件的端口号改为8222application.name改为seata-stock即可其他的都是相同的。 server:port: 8111
spring:
#数据库连接datasource:username: rootpassword: 123456url: jdbc:mysql://localhost:3306/seata-test?characterEncodingutf8useSSLfalseserverTimezoneUTCdriver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourceapplication:name: seata-order#order的服务名称cloud:#nacos的地址nacos:discovery:server-addr: 127.0.0.1:8848username: nacospassword: nacos
seata:
#seata的nacos配置registry:type: nacos#这里的type等同于registry.conf文件的mode nacosnacos:server-addr: 127.0.0.1:8848 #seata所在的nacos服务地址username: nacospassword: nacosconfig:type: nacosnacos:server-addr: 127.0.0.1:8848username: nacospassword: nacos#这里要注意这是我们在配置config.txt文件中讲述的service.vgroupMapping.后面的自定义名称#要跟你在上传配置文件中的组名称一致tx-service-group: my_tx_group
mybatis:mapper-locations: classpath:mapper/*.xmltypeAliasesPackage: com.it.entityconfiguration:mapUnderscoreToCamelCase: trueFegin客户端的配置Order服务需要Stock不需要
1 启动类上加上EnableFeignClients注解 2 创建fegin包并创建一个新的接口StockService
//value的值是要调用的服务名称path是接口前缀路径
FeignClient(value seata-stock, path /stock/)
public interface StockService {//这个方法是修改库存方法RequestMapping(updateStockByOrderId)public String updateStockByOrderId(RequestParam(orderId) Long orderId);
}
Order服务的Controller
RestController
RequestMapping(/order/)
public class SeataOrderController {Resourceprivate ItOrderService orderService;RequestMapping(saveOrder)public String saveOrder() {return orderService.saveOrder();}
}Order服务的ServiceImpl
Service
public class ItOrderServiceImpl extends ServiceImplItOrderMapper, ItOrder implements ItOrderService {Resourceprivate ItOrderMapper orderMapper;Resourceprivate StockService stockService;GlobalTransactionalOverridepublic String saveOrder() {ItOrder order new ItOrder();order.setOrderName(技嘉主板);order.setOrderStatus(2);orderMapper.insert(order);order.setId(1L);stockService.updateStockByOrderId(order.getId());int i 1 / 0;//故意报错return 执行完毕;}
}Stock服务的Controller
RestController
RequestMapping(/stock/)
public class SeataStockController {Resourceprivate ItStockService stockService;RequestMapping(updateStockByOrderId)public void updateStockByOrderId(Long orderId) {stockService.updateStockByOrderId(orderId);}
}Stock服务的ServiceImpl
Service
public class ItStockServiceImpl extends ServiceImplItStockMapper, ItStock implements ItStockService {Resourceprivate ItStockMapper stockMapper;Overridepublic void updateStockByOrderId(Long orderId) {ItStock stock stockMapper.selectOne(new QueryWrapperItStock().eq(order_id, orderId));stock.setRepertory(stock.getRepertory() - 1);stock.setSales(stock.getSales() 1);stockMapper.updateById(stock);}
}代码分析
我们可以看到在order服务中我们在方法上标记了GlobalTransactional注解我们执行完插入语句然后远程调用修改库存服务调用玩库存服务后故意抛出异常来测试两个服务之间是否都可以正常回滚操作
结束
最后的运行结果我就不在这里演示了如果出现了GlobalTransactional注解失效的问题那么有可能是以下原因
Seata Server配置问题如果Seata Server没有正确配置包括事务组ID、事务模式等信息那么使用GlobalTransactional注解时就会失效。分布式事务管理器未启动如果Seata Server未启动或者连接不上那么使用GlobalTransactional注解时也会失效。分布式事务传播机制问题在分布式事务的调用链路中每个服务都需要正确设置事务的传播机制即在业务代码中使用Transactional注解开启本地事务同时在远程调用时正确传递事务上下文。如果其中任何一个服务未正确设置事务传播机制那么GlobalTransactional注解就会失效。事务模式不匹配GlobalTransactional注解的事务模式必须与Seata Server中配置的事务模式匹配否则就会失效。如果Seata Server中配置的是AT模式那么业务代码中使用的就必
总结
seata最难的地方是在于如何配置它当搞清楚他的配置文件使用它只需要一个注解即可跟Spring提供的本地事务注解一样。 今天就分享到这里拜拜啦!