yml
server: port: 2001 spring: application: name: seata-order-service cloud: alibaba: seata: #自定义事务组名称需要与seata-server中的对应 tx-service-group: fsp_tx_group nacos: discovery: server-addr: localhost:8848 datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://mpolaris.top:3306/seata_order?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8 username: root password: 1234321 feign: hystrix: enabled: false logging: level: io: seata: info mybatis: mapperLocations: classpath:mapper/*.xmldomain
//CommonResult @Data @AllArgsConstructor @NoArgsConstructor public class CommonResult<T>{ private Integer code; private String message; private T data; public CommonResult(Integer code, String message) { this(code,message,null); } } //order @Data @AllArgsConstructor @NoArgsConstructor public class Order{ private Long id; private Long userId; private Long productId; private Integer count; private BigDecimal money; private Integer status; //订单状态:0:创建中;1:已完结 }Dao
@Mapper public interface OrderDao{ //1 新建订单 void create(Order order); //2 修改订单状态,从零改为1 void update(@Param("userId") Long userId, @Param("status") Integer status); }service
public interface OrderService{ void create(Order order); } @FeignClient(value = "seata-storage-service") public interface StorageService{ @PostMapping(value = "/storage/decrease") CommonResult decrease(@RequestParam("productId") Long productId, @RequestParam("count") Integer count); } @FeignClient(value = "seata-account-service") public interface AccountService{ @PostMapping(value = "/account/decrease") CommonResult decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money); } @Service @Slf4j public class OrderServiceImpl implements OrderService{ @Resource private OrderDao orderDao; @Resource private StorageService storageService; @Resource private AccountService accountService; /** * 创建订单->调用库存服务扣减库存->调用账户服务扣减账户余额->修改订单状态 * 简单说:下订单->扣库存->减余额->改状态 */ @Override @GlobalTransactional(name="fsp-create-order",rollbackFor=Exception.class) public void create(Order order) { log.info("==> 开始新建订单"); //1 新建订单 orderDao.create(order); //2 扣减库存 log.info("==> 订单微服务开始调用库存,做扣减Count"); storageService.decrease(order.getProductId(),order.getCount()); log.info("==> 订单微服务开始调用库存,做扣减end"); //3 扣减账户 log.info("==> 订单微服务开始调用账户,做扣减Money"); accountService.decrease(order.getUserId(),order.getMoney()); log.info("==> 订单微服务开始调用账户,做扣减end"); //4 修改订单状态,从零到1,1代表已经完成 log.info("==> 修改订单状态开始"); orderDao.update(order.getUserId(),0); log.info("==> 修改订单状态结束"); log.info("==> 下订单结束了,O(∩_∩)O哈哈~"); } }controller
@RestController public class OrderController{ @Resource private OrderService orderService; @GetMapping("/order/create") public CommonResult create(Order order) { orderService.create(order); return new CommonResult(200,"订单创建成功"); } }config
@Configuration public class DataSourceProxyConfig { @Value("${mybatis.mapperLocations}") private String mapperLocations; @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource druidDataSource() { return new DruidDataSource(); } @Bean public DataSourceProxy dataSourceProxy(DataSource dataSource) { return new DataSourceProxy(dataSource); } @Bean public SqlSessionFactory sqlSessionFactoryBean( DataSourceProxy dataSourceProxy)throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSourceProxy); sqlSessionFactoryBean.setMapperLocations( new PathMatchingResourcePatternResolver() .getResources(mapperLocations)); sqlSessionFactoryBean.setTransactionFactory( new SpringManagedTransactionFactory()); return sqlSessionFactoryBean.getObject(); } } @Configuration @MapperScan({"com.polaris.springcloud.dao"}) public class MyBatisConfig { }主启动
@EnableDiscoveryClient @EnableFeignClients @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//取消数据源的自动创建 public class SeataOrderMainApp2001 { public static void main(String[] args) { SpringApplication.run(SeataOrderMainApp2001.class, args); } }mapper
<mapper namespace="com.polaris.springcloud.dao.OrderDao"> <resultMap type="com.polaris.springcloud.domain.Order"> <id column="id" property="id" jdbcType="BIGINT"/> <result column="user_id" property="userId" jdbcType="BIGINT"/> <result column="product_id" property="productId" jdbcType="BIGINT"/> <result column="count" property="count" jdbcType="INTEGER"/> <result column="money" property="money" jdbcType="DECIMAL"/> <result column="status" property="status" jdbcType="INTEGER"/> </resultMap> <insert> insert into t_order (id,user_id,product_id,count,money,status) values (null,#{userId},#{productId},#{count},#{money},0); </insert> <update> update t_order set status = 1 where user_id=#{userId} and status = #{status}; </update> </mapper>将seata-server/conf目录下的file.conf和registry.conf拷贝到项目模块下的resource中(seata-server/conf下的是总控)
新建库存Storage-Module seata-storage-service2002
新建账户Account-Module seata-account-service2003
参考订单Module,源码参考个人GitHub
6.6 测试数据库初始情况
正常下单
:2001/order/create?userId=1&productId=1&count=10&money=100
数据库情况正常
超时异常,没加@GlobalTransactional