每个数据库都需要创建
-- 注意此处0.3.0+ 增加唯一索引 ux_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,
`ext` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
两个不同的数据库db_money_bj和db_money_sh,创建两个相同的表
CREATE TABLE `tb_money` (
`user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`user_name` varchar(255) DEFAULT NULL COMMENT '用户姓名',
`user_money` int(11) NOT NULL DEFAULT '0' COMMENT '账户余额:单位分',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2021.1</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
每个微服务都需要添加依赖和修改配置文件
## seata配置
seata.enabled=true
seata.application-id=server-seata-sh
seata.registry.type=file
seata.config.type=file
seata.service.grouplist.default=127.0.0.1:8091
seata.service.vgroup-mapping.server-seata-money=default
seata.tx-service-group=server-seata-money
seata.client.undo.log-table=undo_log
两个微服务接口代码相同、表名相同、数据库不同
package com.shenmazong.controller;
import com.shenmazong.mapper.TbMoneyMapper;
import com.shenmazong.pojo.TbMoney;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
* @author 军哥
* @version 1.0
* @description: MoneyController
* @date 2022/7/12 11:25
*/
@RestController
@Slf4j
@RequestMapping(value = "/money")
public class MoneyController {
@Autowired
TbMoneyMapper tbMoneyMapper;
@GlobalTransactional
@PostMapping(value = "/pay")
public Object pay(@RequestParam("userId") Integer userId, @RequestParam("money") Integer money) {
TbMoney tbMoney = tbMoneyMapper.selectById(userId);
tbMoney.setUserMoney(tbMoney.getUserMoney()+money);
tbMoneyMapper.updateById(tbMoney);
return tbMoney;
}
}
package com.shenmazong.controller;
import com.shenmazong.service.BjMoneyService;
import com.shenmazong.service.ShMoneyService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 军哥
* @version 1.0
* @description: MoneyController
* @date 2022/7/12 11:52
*/
@RestController
@Slf4j
@RequestMapping(value = "/money")
public class MoneyController {
@Autowired
BjMoneyService bjMoneyService;
@Autowired
ShMoneyService shMoneyService;
@GlobalTransactional
@GetMapping(value = "/turn/{fromId}/{toId}/{money}")
public Object turn(@PathVariable("fromId") Integer fromId,
@PathVariable("toId") Integer toId,
@PathVariable("money") Integer money) throws Exception {
bjMoneyService.pay(fromId, money*(-1));
shMoneyService.pay(toId, money);
return "OK";
}
}
package com.shenmazong.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Component
@FeignClient(name = "server-seata-bj")
public interface BjMoneyService {
@PostMapping(value = "/money/pay")
public Object pay(@RequestParam("userId") Integer userId, @RequestParam("money") Integer money);
}
package com.shenmazong.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Component
@FeignClient(name = "server-seata-sh")
public interface ShMoneyService {
@PostMapping(value = "/money/pay")
public Object pay(@RequestParam("userId") Integer userId, @RequestParam("money") Integer money);
}
这里没有进行异常拦截,但是不影响测试