• Spring cloud alibaba +Nacos+Seata20220602


    1、DB 

     

           seata_order---------------------------------

    CREATE TABLE IF NOT EXISTS `t_order` (
      `id` bigint(11) NOT NULL AUTO_INCREMENT,
      `user_id` bigint(11) DEFAULT NULL COMMENT '用户id',
      `product_id` bigint(11) DEFAULT NULL COMMENT '产品id',
      `count` int(11) DEFAULT NULL COMMENT '数量',
      `money` decimal(11,0) DEFAULT NULL COMMENT '金额',
      `status` int(1) DEFAULT NULL COMMENT '订单状态:0:创建中; 1:已完结',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8;

    Hurt  16:16:12
    CREATE TABLE IF NOT EXISTS `t_order` (
      `id` bigint(11) NOT NULL AUTO_INCREMENT,
      `user_id` bigint(11) DEFAULT NULL COMMENT '用户id',
      `product_id` bigint(11) DEFAULT NULL COMMENT '产品id',
      `count` int(11) DEFAULT NULL COMMENT '数量',
      `money` decimal(11,0) DEFAULT NULL COMMENT '金额',
      `status` int(1) DEFAULT NULL COMMENT '订单状态:0:创建中; 1:已完结',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8;

    -- 正在导出表  seata_order.t_order 的数据:~4 rows (大约)
    /*!40000 ALTER TABLE `t_order` DISABLE KEYS */;
    INSERT INTO `t_order` (`id`, `user_id`, `product_id`, `count`, `money`, `status`) VALUES
    (36, 1, 1, 5, 50, 1),
    (37, 1, 1, 5, 50, 1),
    (38, 1, 1, 5, 50, 1),
    (39, 1, 1, 5, 50, 1);
    /*!40000 ALTER TABLE `t_order` ENABLE KEYS */;

    -- 导出  表 seata_order.undo_log 结构
    CREATE TABLE IF NOT EXISTS `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=170 DEFAULT CHARSET=utf8;

     seata_account ---------------------------------


    -- 导出 seata_account 的数据库结构
    CREATE DATABASE IF NOT EXISTS `seata_account` /*!40100 DEFAULT CHARACTER SET latin1 */;
    USE `seata_account`;

    -- 导出  表 seata_account.t_account 结构
    CREATE TABLE IF NOT EXISTS `t_account` (
      `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
      `user_id` bigint(11) DEFAULT NULL COMMENT '用户id',
      `total` decimal(10,0) DEFAULT NULL COMMENT '总额度',
      `used` decimal(10,0) DEFAULT NULL COMMENT '已用余额',
      `residue` decimal(10,0) DEFAULT '0' COMMENT '剩余可用额度',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

    -- 正在导出表  seata_account.t_account 的数据:~1 rows (大约)
    /*!40000 ALTER TABLE `t_account` DISABLE KEYS */;
    INSERT INTO `t_account` (`id`, `user_id`, `total`, `used`, `residue`) VALUES
    (1, 1, 1000, 0, 1000);
    /*!40000 ALTER TABLE `t_account` ENABLE KEYS */;

    -- 导出  表 seata_account.undo_log 结构
    CREATE TABLE IF NOT EXISTS `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=23 DEFAULT CHARSET=utf8;

     seata_storage ---------------------------------

    -- 导出 seata_storage 的数据库结构
    CREATE DATABASE IF NOT EXISTS `seata_storage` /*!40100 DEFAULT CHARACTER SET latin1 */;
    USE `seata_storage`;

    -- 导出  表 seata_storage.t_storage 结构
    CREATE TABLE IF NOT EXISTS `t_storage` (
      `id` bigint(11) NOT NULL AUTO_INCREMENT,
      `product_id` bigint(11) DEFAULT NULL COMMENT '产品id',
      `total` int(11) DEFAULT NULL COMMENT '总库存',
      `used` int(11) DEFAULT NULL COMMENT '已用库存',
      `residue` int(11) DEFAULT NULL COMMENT '剩余库存',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

    -- 正在导出表  seata_storage.t_storage 的数据:~1 rows (大约)
    /*!40000 ALTER TABLE `t_storage` DISABLE KEYS */;
    INSERT INTO `t_storage` (`id`, `product_id`, `total`, `used`, `residue`) VALUES
    (1, 1, 1000, 0, 1000);

    2、Seate 配置 

     

    3、Nacos

    4、Seata-order,

           Seata-storage ,  Seata-account

       

    seate-order*******************************************
    1)、pom.xml
    <properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    <spring-cloud-alibaba.version>2.2.2.RELEASE</spring-cloud-alibaba.version>
    <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
    </properties>
    <dependencies>
    <!--nacos openfeign-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!--seata-->
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <exclusions>
    <exclusion>
    <artifactId>seata-all</artifactId>
    <groupId>io.seata</groupId>
    </exclusion>
    </exclusions>
    </dependency>
    <dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-all</artifactId>
    <version>1.3.0</version>
    </dependency>
    <!--db-->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    </dependency>
    <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.4</version>
    </dependency>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
    </dependency>
    </dependencies>
    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>${spring-cloud.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>${spring-boot.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>${spring-cloud-alibaba.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    </dependencies>
    </dependencyManagement>

    2)、application.properties

    spring.application.name=seata-order-service
    server.port=2022
    spring.cloud.alibaba.seata.tx-service-group=my_test_tx_group

    # 数据库驱动:
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/seata_order?serverTimezone=UTC
    spring.datasource.username=root
    spring.datasource.password=root
    # Nacos
    spring.cloud.nacos.discovery.username=nacos
    spring.cloud.nacos.discovery.password=nacos
    spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
    #namespace,默认为 public
    spring.cloud.nacos.discovery.namespace=public
    ###feign
    feign.hystrix.enabled=false
    logging.level.io.seata=info

    #指定Mybatis的Mapper文件
    mybatis.mapper-locations=classpath:mapper/*xml


    3)、OrderMapper.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

    <mapper namespace="com.sc.seate2022.dao.OrderDao">

    <resultMap id="BaseResultMap" type="com.sc.seate2022.model.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 id="create">
    insert into t_order (id,user_id,product_id,count,money,status)
    values (null,#{userId},#{productId},#{count},#{money},0);
    </insert>

    <update id="update">
    update t_order set status = 1
    where user_id=#{userId} and status = #{status};
    </update>
    </mapper>

    4)、Seate2022Application

    @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
    @EnableDiscoveryClient
    @EnableFeignClients
    public class Seate2022Application {

    public static void main(String[] args) {
    SpringApplication.run(Seate2022Application.class, args);
    }

    }

    5)、CommonResult
    package com.sc.seate2022.Utils;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;

    @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);
    }
    }

    6)、Order
    package com.sc.seate2022.model;
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Order {
    private Long id;
    private Long userId;
    private Long productId;
    private Integer count;
    private BigDecimal money;
    /**
    * 订单状态 0创建中;1:已完结
    */
    private Integer status;
    }

    7)、OrderDao
    package com.sc.seate2022.dao;
    @Mapper
    public interface OrderDao {
    void create(Order order);
    void update(@Param("userId") Long userId,@Param("status") Integer status);
    }

    8)、service

    ###################################
    com.sc.seate2022.service.Interface

    package com.sc.seate2022.service.Interface;
    @FeignClient(value = "seata-account-service")
    public interface AccountService {

    @GetMapping("/account/decrease")
    public CommonResult decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money);
    }


    @FeignClient(value = "seata-storage-service")
    public interface StorageService {
    /**
    *
    * @param productId
    * @param count
    * @return
    */
    @GetMapping(value = "/storage/decrease")
    CommonResult decrease(@RequestParam("productId") Long productId, @RequestParam("count") Integer count);
    }

    ###################################
    com.sc.seate2022.service

    @Service
    @Slf4j
    public class OrderService {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private StorageService storageService;

    @Autowired
    private AccountService accountService;

    /**
    * 创建订单->调用库存服务扣减库存->调用账户服务扣减账户余额->修改订单状态
    * 切记,第一次启动将该注解注释调
    */
    @GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class)

    public void create(Order order){
    log.info("----->开始新建订单");
    //新建订单,调用本服务接口
    orderDao.create(order);

    //扣减库存,通过openFeign远程调用库存服务
    log.error("----->订单微服务开始调用库存,做扣减Count");
    storageService.decrease(order.getProductId(),order.getCount());
    log.error("----->订单微服务开始调用库存,做扣减end");

    //扣减账户。通过openFeign远程调用账户服务
    log.error("----->订单微服务开始调用账户,做扣减Money");
    accountService.decrease(order.getUserId(),order.getMoney());
    log.error("----->订单微服务开始调用账户,做扣减end");

    //修改订单状态,从零到1代表已经完成,调用本服务
    log.error("----->修改订单状态开始");
    orderDao.update(order.getUserId(),0);
    log.error("----->修改订单状态结束");

    log.info("----->下订单结束了");
    }
    }

    9)、controller
    com.sc.seate2022.controller
    @RestController
    @Slf4j
    public class OrderController {
    @Resource
    private OrderService orderService;

    @GetMapping(value = "/order/create")
    public CommonResult create(Order order){
    orderService.create(order);
    return new CommonResult(200,"订单创建成功!");
    }
    }


    10)、config
    @Configuration
    public class DataSourceProxyConfig {
    @Value("${mybatis.mapper-locations}")
    private String mapperLocations;


    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource 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.sc.seate2022.dao"})
    public class MyBatisConfig {
    }

    seate-account*******************************************
    1)、pom.xml
    <properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    <spring-cloud-alibaba.version>2.2.2.RELEASE</spring-cloud-alibaba.version>
    <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
    </properties>
    <dependencies>
    <!--nacos openfeign-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!--seata-->
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <exclusions>
    <exclusion>
    <artifactId>seata-all</artifactId>
    <groupId>io.seata</groupId>
    </exclusion>
    </exclusions>
    </dependency>
    <dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-all</artifactId>
    <version>1.3.0</version>
    </dependency>
    <!--db-->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    </dependency>
    <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.4</version>
    </dependency>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
    </dependency>
    </dependencies>
    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>${spring-cloud.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>${spring-boot.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>${spring-cloud-alibaba.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    </dependencies>
    </dependencyManagement>

    2)、application.properties

    spring.application.name=seata-account-service
    server.port=2024
    spring.cloud.alibaba.seata.tx-service-group=my_test_tx_group


    # 数据库驱动:
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/seata_account?serverTimezone=UTC
    spring.datasource.username=root
    spring.datasource.password=root
    # Nacos
    spring.cloud.nacos.discovery.username=nacos
    spring.cloud.nacos.discovery.password=nacos
    spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
    #namespace,默认为 public
    spring.cloud.nacos.discovery.namespace=public
    ###feign
    feign.hystrix.enabled=false
    logging.level.io.seata=info

    #指定Mybatis的Mapper文件
    mybatis.mapper-locations=classpath:mapper/*xml


    3)、AccountMapper.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.sc.seateaccountservice.dao.AccountDao">
    <resultMap id="BaseResultMap" type="com.sc.seateaccountservice.model.Account">
    <id column="id" property="id" jdbcType="BIGINT"/>
    <result column="user_id" property="userId" jdbcType="BIGINT"/>
    <result column="total" property="total" jdbcType="DECIMAL"/>
    <result column="used" property="used" jdbcType="DECIMAL"/>
    <result column="residue" property="residue" jdbcType="DECIMAL"/>
    </resultMap>

    <update id="decrease">
    UPDATE t_account
    SET
    residue = residue - #{money},used = used + #{money}
    WHERE
    user_id = #{userId};
    </update>
    </mapper>

    4)、SeateAccountServiceApplication

    @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
    @EnableDiscoveryClient
    @EnableFeignClients
    public class SeateAccountServiceApplication {

    public static void main(String[] args) {
    SpringApplication.run(SeateAccountServiceApplication.class, args);
    }

    }

    5)、CommonResult
    package com.sc.seateaccountservice.Utils;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;

    @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);
    }
    }

    6)、Account
    package com.sc.seateaccountservice.model;
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Account {
    private Long id;
    //用户ID
    private Long userId;
    //总额度
    private BigDecimal total;
    //已用额度
    private BigDecimal used;
    //剩余额度
    private BigDecimal residue;
    }

    7)、AccountDao
    package com.sc.seateaccountservice.dao;
    @Mapper
    public interface AccountDao {
    /**
    * 扣减账户余额
    * @param userId
    * @param money
    */
    void decrease(@Param("userId") Long userId, @Param("money") BigDecimal money);
    }


    8)、service
    package com.sc.seateaccountservice.service;
    ###################################
    @Service
    @Slf4j
    public class AccountService {

    private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class);
    @Resource
    private AccountDao accountDao;
    /**
    * 扣减账户余额
    */
    public void decrease(Long userId, BigDecimal money) {

    /* LOGGER.error("------->account-service中扣减账户余额开始");
    try {
    TimeUnit.SECONDS.sleep(20);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }*/
    accountDao.decrease(userId,money);
    LOGGER.error("------->account-service中扣减账户余额结束");
    }
    }

    9)、controller
    com.sc.seateaccountservice.controller

    @RestController
    @Slf4j
    public class AccountController {

    @Resource
    private AccountService accountService;

    /**
    * 扣减账户余额
    */
    @GetMapping("/account/decrease")
    public CommonResult decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money){
    accountService.decrease(userId,money);
    return new CommonResult(200,"扣减账户余额成功!");
    }

    }

    10)、config
    @Configuration
    public class DataSourceProxyConfig {
    @Value("${mybatis.mapper-locations}")
    private String mapperLocations;


    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource 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.sc.package com.sc.seateaccountservice.service.dao"})

    public class MyBatisConfig {
    }

    seate-stoage*******************************************
    1)、pom.xml
    <properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    <spring-cloud-alibaba.version>2.2.2.RELEASE</spring-cloud-alibaba.version>
    <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
    </properties>
    <dependencies>
    <!--nacos openfeign-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!--seata-->
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <exclusions>
    <exclusion>
    <artifactId>seata-all</artifactId>
    <groupId>io.seata</groupId>
    </exclusion>
    </exclusions>
    </dependency>
    <dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-all</artifactId>
    <version>1.3.0</version>
    </dependency>
    <!--db-->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    </dependency>
    <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.4</version>
    </dependency>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
    </dependency>
    </dependencies>
    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>${spring-cloud.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>${spring-boot.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>${spring-cloud-alibaba.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    </dependencies>
    </dependencyManagement>

    2)、application.properties

    spring.application.name=seata-storage-service
    server.port=2023
    spring.cloud.alibaba.seata.tx-service-group=my_test_tx_groupp


    # 数据库驱动:
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/seata_storage?serverTimezone=UTC
    spring.datasource.username=root
    spring.datasource.password=root
    # Nacos
    spring.cloud.nacos.discovery.username=nacos
    spring.cloud.nacos.discovery.password=nacos
    spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
    #namespace,默认为 public
    spring.cloud.nacos.discovery.namespace=public
    ###feign
    feign.hystrix.enabled=false
    logging.level.io.seata=info

    #指定Mybatis的Mapper文件
    mybatis.mapper-locations=classpath:mapper/*xml


    3)、StorageMapper.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.sc.seatastorageservice.dao.StorageDao">

    <resultMap id="BaseResultMap" type="com.sc.seatastorageservice.model.Storage">
    <id column="id" property="id" jdbcType="BIGINT"/>
    <result column="product_id" property="productId" jdbcType="BIGINT"/>
    <result column="total" property="total" jdbcType="INTEGER"/>
    <result column="used" property="used" jdbcType="INTEGER"/>
    <result column="residue" property="residue" jdbcType="INTEGER"/>
    </resultMap>

    <update id="decrease">
    UPDATE
    t_storage
    SET
    used = used + #{count},residue = residue - #{count}
    WHERE
    product_id = #{productId}
    </update>

    </mapper>


    4)、SeateStorageServiceApplication

    @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
    @EnableDiscoveryClient
    @EnableFeignClients
    public class SeateStorageServiceApplication{

    public static void main(String[] args) {
    SpringApplication.run(SeateStorageServiceApplication.class, args);
    }

    }

    5)、CommonResult
    package com.sc.seatestorageservice.Utils;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;

    @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);
    }
    }

    6)、Storage
    package com.sc.seatestorageservice.model;
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Storage {
    private Long id;
    //产品id
    private Long productId;
    //总库存
    private Integer total;
    //已用库存
    private Integer used;
    //剩余库存
    private Integer resiude;
    }


    7)、StorageDao
    package com.sc.seatestorageservice.dao;
    @Mapper
    public interface StorageDao {
    /**扣减库存信息
    *
    * @param productId
    * @param count
    */
    void decrease(@Param("productId") Long productId, @Param("count") Integer count);
    }

    8)、service
    package com.sc.seateastorageservice.service;
    ###################################
    @Service
    @Slf4j
    public class StorageService{


    private static final Logger LOGGER = LoggerFactory.getLogger(StorageService.class);

    @Resource
    private StorageDao storageDao;


    /**
    * 扣减库存
    *
    * @param productId
    * @param count
    */
    public void decrease(Long productId, Integer count) {
    LOGGER.info("------->storage-service中扣减库存开始");
    storageDao.decrease(productId,count);
    LOGGER.info("------->storage-service中扣减库存结束");
    }
    }

    9)、controller
    com.sc.seatestorageservice.controller

    @RestController
    @Slf4j
    public class StorageController{

    private StorageService storageService;

    /**storageService
    *
    * @param productId
    * @param count
    * @return
    */
    @GetMapping("/storage/decrease")
    public CommonResult decrease(Long productId, Integer count) {
    storageService.decrease(productId, count);
    return new CommonResult(200,"扣减库存成功!");
    }

    }

    10)、config
    @Configuration
    public class DataSourceProxyConfig {
    @Value("${mybatis.mapper-locations}")
    private String mapperLocations;


    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource 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.sc.package com.sc.seatastorageservice.service.dao"})
    public class MyBatisConfig {
    }

    5、测试

     

    参考:https://www.cnblogs.com/dgjword/p/13857210.html

  • 相关阅读:
    通过精灵图片序列单元制作Html+CSS3 动画
    App开发三种模式
    Matrix
    MySQL SQL
    Git和GitHub
    Web前端入门了解
    LayoutInflater和inflate()
    使用XML文件和Java代码控制UI界面
    Android Handler
    Android Gradle的使用
  • 原文地址:https://www.cnblogs.com/smallfa/p/16338388.html
Copyright © 2020-2023  润新知