Seata2_案例

[TOC]

1.Seata之Order-Module配置搭建

新建module:seata-order-service2001
下订单 -> 减库存 -> 扣余额 -> 改(订单)状态
seata-order-service2001
POM

  1. <dependencies>
  2. <!--nacos-->
  3. <dependency>
  4. <groupId>com.alibaba.cloud</groupId>
  5. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  6. </dependency>
  7. <!--seata-->
  8. <dependency>
  9. <groupId>com.alibaba.cloud</groupId>
  10. <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
  11. <exclusions>
  12. <exclusion>
  13. <artifactId>seata-all</artifactId>
  14. <groupId>io.seata</groupId>
  15. </exclusion>
  16. </exclusions>
  17. </dependency>
  18. <dependency>
  19. <groupId>io.seata</groupId>
  20. <artifactId>seata-all</artifactId>
  21. <version>1.4.2</version>
  22. </dependency>
  23. <!--feign-->
  24. <dependency>
  25. <groupId>org.springframework.cloud</groupId>
  26. <artifactId>spring-cloud-starter-openfeign</artifactId>
  27. </dependency>
  28. <!--web-actuator-->
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter-web</artifactId>
  32. </dependency>
  33. <dependency>
  34. <groupId>org.springframework.boot</groupId>
  35. <artifactId>spring-boot-starter-actuator</artifactId>
  36. </dependency>
  37. <!--mysql-druid-->
  38. <dependency>
  39. <groupId>mysql</groupId>
  40. <artifactId>mysql-connector-java</artifactId>
  41. </dependency>
  42. <dependency>
  43. <groupId>com.alibaba</groupId>
  44. <artifactId>druid-spring-boot-starter</artifactId>
  45. </dependency>
  46. <dependency>
  47. <groupId>org.mybatis.spring.boot</groupId>
  48. <artifactId>mybatis-spring-boot-starter</artifactId>
  49. </dependency>
  50. <dependency>
  51. <groupId>org.springframework.boot</groupId>
  52. <artifactId>spring-boot-starter-test</artifactId>
  53. <scope>test</scope>
  54. </dependency>
  55. <dependency>
  56. <groupId>org.projectlombok</groupId>
  57. <artifactId>lombok</artifactId>
  58. <optional>true</optional>
  59. </dependency>
  60. </dependencies>

配置文件 yml

  1. server:
  2. port: 2001
  3. spring:
  4. application:
  5. name: seata-order-service
  6. cloud:
  7. alibaba:
  8. seata:
  9. #自定义事务组名称需要与seata-server中的对应
  10. tx-service-group: fsp_tx_group
  11. nacos:
  12. discovery:
  13. server-addr: localhost:8848
  14. datasource:
  15. driver-class-name: com.mysql.cj.jdbc.Driver
  16. url: jdbc:mysql://localhost:3306/seata_order
  17. username: root
  18. password: 123456
  19. feign:
  20. hystrix:
  21. enabled: false
  22. logging:
  23. level:
  24. io:
  25. seata: info
  26. mybatis:
  27. mapperLocations: classpath:mapper/*.xml

domain

  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. public class Order
  5. {
  6. private Long id;
  7. private Long userId;
  8. private Long productId;
  9. private Integer count;
  10. private BigDecimal money;
  11. private Integer status; //订单状态:0:创建中;1:已完结
  12. }

2.Seata之Order-Module撸码(上)

Dao接口及实现

  1. @Mapper
  2. public interface OrderDao {
  3. //1 新建订单
  4. void create(Order order);
  5. //2 修改订单状态,从零改为1
  6. void update(@Param("userId") Long userId, @Param("status") Integer status);
  7. }

OrderDao.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3. <mapper namespace="com.zds.egg.dao.OrderDao">
  4. <resultMap id="BaseResultMap" type="ccom.zds.egg.dao.domain.Order">
  5. <id column="id" property="id" jdbcType="BIGINT"/>
  6. <result column="user_id" property="userId" jdbcType="BIGINT"/>
  7. <result column="product_id" property="productId" jdbcType="BIGINT"/>
  8. <result column="count" property="count" jdbcType="INTEGER"/>
  9. <result column="money" property="money" jdbcType="DECIMAL"/>
  10. <result column="status" property="status" jdbcType="INTEGER"/>
  11. </resultMap>
  12. <insert id="create">
  13. insert into t_order (id,user_id,product_id,count,money,status)
  14. values (null,#{userId},#{productId},#{count},#{money},0);
  15. </insert>
  16. <update id="update">
  17. update t_order set status = 1
  18. where user_id=#{userId} and status = #{status};
  19. </update>
  20. </mapper>

Service接口及实现

  • OrderService
    • OrderServiceImpl
  • StorageService
  • AccountService

    1. public interface OrderService {
    2. void create(Order order);
    3. }
    1. @FeignClient(value = "seata-account-service")
    2. public interface AccountService {
    3. @PostMapping(value = "/account/decrease")
    4. SingleResult decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money);
    5. }
    1. @FeignClient(value = "seata-storage-service")
    2. public interface StorageService {
    3. @PostMapping(value = "/storage/decrease")
    4. SingleResult decrease(@RequestParam("productId") Long productId, @RequestParam("count") Integer count);
    5. }
    1. @Service
    2. @Slf4j
    3. public class OrderServiceImpl implements OrderService {
    4. @Resource
    5. private OrderDao orderDao;
    6. @Resource
    7. private StorageService storageService;
    8. @Resource
    9. private AccountService accountService;
    10. @Override
    11. public void create(Order order) {
    12. log.info("----->开始新建订单");
    13. //1 新建订单
    14. orderDao.create(order);
    15. //2 扣减库存
    16. log.info("----->订单微服务开始调用库存,做扣减Count");
    17. storageService.decrease(order.getProductId(),order.getCount());
    18. log.info("----->订单微服务开始调用库存,做扣减end");
    19. //3 扣减账户
    20. log.info("----->订单微服务开始调用账户,做扣减Money");
    21. accountService.decrease(order.getUserId(),order.getMoney());
    22. log.info("----->订单微服务开始调用账户,做扣减end");
    23. //4 修改订单状态,从零到1,1代表已经完成
    24. log.info("----->修改订单状态开始");
    25. orderDao.update(order.getUserId(),0);
    26. log.info("----->修改订单状态结束");
    27. log.info("----->下订单结束了,O(∩_∩)O哈哈~");
    28. }
    29. }

    3.Seata之Order-Module撸码(下)

    Controller

    1. @RestController
    2. public class OrderController
    3. {
    4. @Resource
    5. private OrderService orderService;
    6. @GetMapping("/order/create")
    7. public SingleResult create(Order order)
    8. {
    9. orderService.create(order);
    10. return new SingleResult().success("","订单创建成功");
    11. }
    12. }

    Config配置

  • MyBatisConfig

  • DataSourceProxyConfig
    1. import org.mybatis.spring.annotation.MapperScan;
    2. import org.springframework.context.annotation.Configuration;
    3. @Configuration
    4. @MapperScan({"com.zds.egg.dao"})
    5. public class MyBatisConfig {
    6. }
    1. import com.alibaba.druid.pool.DruidDataSource;
    2. import io.seata.rm.datasource.DataSourceProxy;
    3. import org.apache.ibatis.session.SqlSessionFactory;
    4. import org.mybatis.spring.SqlSessionFactoryBean;
    5. import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
    6. import org.springframework.beans.factory.annotation.Value;
    7. import org.springframework.boot.context.properties.ConfigurationProperties;
    8. import org.springframework.context.annotation.Bean;
    9. import org.springframework.context.annotation.Configuration;
    10. import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    11. import javax.sql.DataSource;
    12. /**
    13. * 使用Seata对数据源进行代理
    14. */
    15. @Configuration
    16. public class DataSourceProxyConfig {
    17. @Value("${mybatis.mapperLocations}")
    18. private String mapperLocations;
    19. @Bean
    20. @ConfigurationProperties(prefix = "spring.datasource")
    21. public DataSource druidDataSource(){
    22. return new DruidDataSource();
    23. }
    24. @Bean
    25. public DataSourceProxy dataSourceProxy(DataSource dataSource) {
    26. return new DataSourceProxy(dataSource);
    27. }
    28. @Bean
    29. public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception {
    30. SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
    31. sqlSessionFactoryBean.setDataSource(dataSourceProxy);
    32. sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
    33. sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
    34. return sqlSessionFactoryBean.getObject();
    35. }
    36. }
    主启动
    1. import org.springframework.boot.SpringApplication;
    2. import org.springframework.boot.autoconfigure.SpringBootApplication;
    3. import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    5. import org.springframework.cloud.openfeign.EnableFeignClients;
    6. @EnableDiscoveryClient
    7. @EnableFeignClients
    8. //取消数据源的自动创建,而是使用自己定义的
    9. @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
    10. public class SeataOrderMainApp2001
    11. {
    12. public static void main(String[] args)
    13. {
    14. SpringApplication.run(SeataOrderMainApp2001.class, args);
    15. }
    16. }

    4.Seata之Storage-Module说明

    5.Seata之Account-Module说明

    6.Seata之@GlobalTransactional验证

    7.Seata之原理简介