《微服务实战》 第三十一章 ShardingSphere - ShardingSphere-JDBC(下)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 《微服务实战》 第三十一章 ShardingSphere - ShardingSphere-JDBC(下)

1.3.5.3、实现类

@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
    @Override
    @Transactional
    public UserInfo saveUserInfo(UserInfo userInfo) {
        userInfo.setId(IdUtils.getId());
        this.save(userInfo);
        return userInfo;
    }
    @Override
    public UserInfo getUserInfoById(Long id) {
        return this.getById(id);
    }
    @Override
    public List<UserInfo> listUserInfo() {
        QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
        userInfoQueryWrapper.between("id",1623695688380448768L,1623695688380448769L);
        return this.list(userInfoQueryWrapper);
    }
}

1.3.6、生成ID - 雪花算法

package com.xxxx.tore.common.utils;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
/**
 * 生成各种组件ID
 */
public class IdUtils {
    /**
     * 雪花算法
     * @return
     */
    public static long getId(){
        Snowflake snowflake = IdUtil.getSnowflake(0, 0);
        long id = snowflake.nextId();
        return id;
    }
}

1.4、seata与sharding-jdbc整合

https://github.com/seata/seata-samples/tree/master/springcloud-seata-sharding-jdbc-mybatis-plus-samples

1.4.1、common中添加依赖

<!--seata依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <version>2021.0.4.0</version>
</dependency>
<!-- sharding-jdbc整合seata分布式事务-->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-transaction-base-seata-at</artifactId>
    <version>4.1.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2021.0.4.0</version>
    <exclusions>
        <exclusion>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-client</artifactId>
    <version>1.4.2</version>
</dependency>

1.4.2、改造account-service服务

@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements AccountService {
    @Autowired
    private OrderService orderService;
    @Autowired
    private StorageService storageService;
    /**
     * 存放商品编码及其对应的价钱
     */
    private static Map<String,Integer> map = new HashMap<>();
    static {
        map.put("c001",3);
        map.put("c002",5);
        map.put("c003",10);
        map.put("c004",6);
    }
    @Override
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public void debit(OrderDTO orderDTO) {
        //扣减账户余额
        int calculate = this.calculate(orderDTO.getCommodityCode(), orderDTO.getCount());
        AccountDTO accountDTO = new AccountDTO(orderDTO.getUserId(), calculate);
        QueryWrapper<Account> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("id",1);
        objectQueryWrapper.eq(accountDTO.getUserId() != null,"user_id",accountDTO.getUserId());
        Account account = this.getOne(objectQueryWrapper);
        account.setMoney(account.getMoney() - accountDTO.getMoney());
        this.saveOrUpdate(account);
        //扣减库存
        this.storageService.deduct(new StorageDTO(null,orderDTO.getCommodityCode(),orderDTO.getCount()));
        //生成订单
        this.orderService.create(orderDTO);      
    }
    /**
     * 计算购买商品的总价钱
     * @param commodityCode
     * @param orderCount
     * @return
     */
    private int calculate(String commodityCode, int orderCount){
        //商品价钱
        Integer price = map.get(commodityCode) == null ? 0 : map.get(commodityCode);
        return price * orderCount;
    }
}

注意:调单生成调用的逻辑修改,减余额->减库存->生成订单。调用入口方法注解加上:@ShardingTransactionType(TransactionType.BASE)

1.4.3、修改business-service服务

@Service
public class BusinessServiceImpl implements BusinessService {
    @Autowired
    private OrderService orderService;
    @Autowired
    private StorageService storageService;
    @Autowired
    private AccountService accountService;
    @Override
    public void purchase(OrderDTO orderDTO) {
        //扣减账号中的钱
        accountService.debit(orderDTO);        
    }
}

1.4.4、修改order-service服务

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper,Order> implements OrderService {
    /**
     * 存放商品编码及其对应的价钱
     */
    private static Map<String,Integer> map = new HashMap<>();
    static {
        map.put("c001",3);
        map.put("c002",5);
        map.put("c003",10);
        map.put("c004",6);
    }
    @Override
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public Order create(String userId, String commodityCode, int orderCount) {
        int orderMoney = calculate(commodityCode, orderCount);
        Order order = new Order();
        order.setUserId(userId);
        order.setCommodityCode(commodityCode);
        order.setCount(orderCount);
        order.setMoney(orderMoney);
        //保存订单
        this.save(order);
        try {
            TimeUnit.SECONDS.sleep(30);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(true){
            throw new RuntimeException("回滚测试");
        }
        return order;
    }
    /**
     * 计算购买商品的总价钱
     * @param commodityCode
     * @param orderCount
     * @return
     */
    private int calculate(String commodityCode, int orderCount){
        //商品价钱
        Integer price = map.get(commodityCode) == null ? 0 : map.get(commodityCode);
        return price * orderCount;
    }
}

1.4.5、配置文件参考

server:
  port: 8090
spring:
  main:
    # 一个实体类对应多张表,覆盖
    allow-bean-definition-overriding: true
  shardingsphere:
    datasource:
      ds0:
        #配置数据源具体内容,包含连接池,驱动,地址,用户名和密码
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/account?autoReconnect=true&allowMultiQueries=true
        password: root
        type: com.zaxxer.hikari.HikariDataSource
        username: root
      ds1:
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/account?autoReconnect=true&allowMultiQueries=true
        password: root
        type: com.zaxxer.hikari.HikariDataSource
        username: root
      # 配置数据源,给数据源起名称
      names: ds0,ds1
    props:
      sql:
        show: true
    sharding:
      tables:
        account_tbl:
          actual-data-nodes: ds0.account_tbl_${0..1}
          database-strategy:
            standard:
              preciseAlgorithmClassName: com.xxxx.store.account.config.PreciseDBExtShardingAlgorithm
              #rangeAlgorithmClassName: com.xxxx.store.account.config.RangeDBShardingAlgorithm
              sharding-column: id
          table-strategy:
            standard:
              preciseAlgorithmClassName: com.xxxx.store.account.config.PreciseTablesExtShardingAlgorithm
              #rangeAlgorithmClassName: com.xxxx.store.account.config.RangeTablesShardingAlgorithm
              sharding-column: id
        user_info:
          #指定 user_info 表分布情况,配置表在哪个数据库里面,表名称都是什么
          actual-data-nodes: ds0.user_info_${0..9}
          database-strategy:
            standard:
              preciseAlgorithmClassName: com.xxxx.store.account.config.PreciseDBShardingAlgorithm
              rangeAlgorithmClassName: com.xxxx.store.account.config.RangeDBShardingAlgorithm
              sharding-column: id
          table-strategy:
            standard:
              preciseAlgorithmClassName: com.xxxx.store.account.config.PreciseTablesShardingAlgorithm
              rangeAlgorithmClassName: com.xxxx.store.account.config.RangeTablesShardingAlgorithm
              sharding-column: id
  #以上是sharding-jdbc配置
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        namespace: 1ff3782d-b62d-402f-8bc4-ebcf40254d0a
  application:
    name: account-service  #微服务名称
#  datasource:
#    username: root
#    password: root
#    url: jdbc:mysql://127.0.0.1:3306/account
#    driver-class-name: com.mysql.cj.jdbc.Driver
seata:
  enabled: true
  enable-auto-data-source-proxy: false
  application-id: account-service
  tx-service-group: default_tx_group
  service:
    vgroup-mapping:
      default_tx_group: default
    disable-global-transaction: false
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      namespace: 1ff3782d-b62d-402f-8bc4-ebcf40254d0a
      group: SEATA_GROUP
      username: nacos
      password: nacos
  config:
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: 1ff3782d-b62d-402f-8bc4-ebcf40254d0a
      group: SEATA_GROUP
      username: nacos
      password: nacos


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
6月前
|
存储 NoSQL API
微服务——MongoDB实战演练——需求分析
本文档《5-MongoDB实战演练》聚焦于某头条文章评论业务的需求分析与功能实现。基于MongoDB,需完成以下功能:1)提供基本的增删改查API;2)支持通过文章ID查询相关评论;3)实现评论点赞功能。结合实际业务场景,演示MongoDB在数据存储与操作中的应用,附带示意图帮助理解业务结构。
80 2
微服务——MongoDB实战演练——需求分析
|
6月前
|
NoSQL MongoDB 微服务
微服务——MongoDB实战演练——文章评论的基本增删改查
本节介绍了文章评论的基本增删改查功能实现。首先,在`cn.itcast.article.dao`包下创建数据访问接口`CommentRepository`,继承`MongoRepository`以支持MongoDB操作。接着,在`cn.itcast.article.service`包下创建业务逻辑类`CommentService`,通过注入`CommentRepository`实现保存、更新、删除及查询评论的功能。最后,新建Junit测试类`CommentServiceTest`,对保存和查询功能进行测试,并展示测试结果截图,验证功能的正确性。
106 2
|
6月前
|
NoSQL Java MongoDB
微服务——MongoDB实战演练——文章评论实体类的编写
本节主要介绍文章评论实体类的编写,创建了包`cn.itcast.article.po`用于存放实体类。具体实现中,`Comment`类通过`@Document`注解映射到MongoDB的`comment`集合,包含主键、内容、发布时间、用户ID、昵称等属性,并通过`@Indexed`和`@CompoundIndex`注解添加单字段及复合索引,以提升查询效率。同时提供了Mongo命令示例,便于理解和操作。
100 2
|
6月前
|
NoSQL 测试技术 MongoDB
微服务——MongoDB实战演练——MongoTemplate实现评论点赞
本节介绍如何使用MongoTemplate实现评论点赞功能。传统方法通过查询整个文档并更新所有字段,效率较低。为优化性能,采用MongoTemplate对特定字段直接操作。代码中展示了如何利用`Query`和`Update`对象构建更新逻辑,通过`update.inc(&quot;likenum&quot;)`实现点赞数递增。测试用例验证了功能的正确性,确保点赞数成功加1。
111 0
|
6月前
|
NoSQL 测试技术 MongoDB
微服务——MongoDB实战演练——根据上级ID查询文章评论的分页列表
本节介绍如何根据上级ID查询文章评论的分页列表,主要包括以下内容:(1)在CommentRepository中新增`findByParentid`方法,用于按父ID查询子评论分页列表;(2)在CommentService中新增`findCommentListPageByParentid`方法,封装分页逻辑;(3)提供JUnit测试用例,验证功能正确性;(4)使用Compass插入测试数据并执行测试,展示查询结果。通过这些步骤,实现对评论的高效分页查询。
91 0
|
6月前
|
NoSQL MongoDB 微服务
微服务——MongoDB实战演练——文章微服务模块搭建
本节介绍文章微服务模块的搭建过程,主要包括以下步骤:(1)创建项目工程 *article*,并在 *pom.xml* 中引入依赖;(2)配置 *application.yml* 文件;(3)创建启动类 *cn.itcast.article.ArticleApplication*;(4)启动项目,确保控制台无错误提示。通过以上步骤,完成文章微服务模块的基础构建与验证。
75 0
|
3月前
|
NoSQL Java 微服务
2025 年最新 Java 面试从基础到微服务实战指南全解析
《Java面试实战指南:高并发与微服务架构解析》 本文针对Java开发者提供2025版面试技术要点,涵盖高并发电商系统设计、微服务架构实现及性能优化方案。核心内容包括:1)基于Spring Cloud和云原生技术的系统架构设计;2)JWT认证、Seata分布式事务等核心模块代码实现;3)数据库查询优化与高并发处理方案,响应时间从500ms优化至80ms;4)微服务调用可靠性保障方案。文章通过实战案例展现Java最新技术栈(Java 17/Spring Boot 3.2)的应用.
204 9
|
3月前
|
缓存 负载均衡 监控
微服务架构下的电商API接口设计:策略、方法与实战案例
本文探讨了微服务架构下的电商API接口设计,旨在打造高效、灵活与可扩展的电商系统。通过服务拆分(如商品、订单、支付等模块)和标准化设计(RESTful或GraphQL风格),确保接口一致性与易用性。同时,采用缓存策略、负载均衡及限流技术优化性能,并借助Prometheus等工具实现监控与日志管理。微服务架构的优势在于支持敏捷开发、高并发处理和独立部署,满足电商业务快速迭代需求。未来,电商API设计将向智能化与安全化方向发展。
|
6月前
|
NoSQL MongoDB 数据库
微服务——MongoDB实战演练——表结构分析
本文档来源于数据库articledb,展示了一张图片资源。图片宽度为1207像素,高度607像素,采用内联显示方式。内容涉及图像处理与样式设定,适用于文档或网页设计中多媒体元素的布局参考。图片来源为cdn.nlark.com,支持webp格式并附带水印处理。
69 1
微服务——MongoDB实战演练——表结构分析
|
6月前
|
NoSQL Java 数据库连接
微服务——MongoDB实战演练——技术选型
本节主要介绍技术选型中的两个重要工具:**mongodb-driver** 和 **SpringDataMongoDB**。其中,mongodb-driver 是 MongoDB 官方提供的 Java 驱动包,用于连接和操作 MongoDB 数据库,功能类似 JDBC 驱动。通过官方示例可快速上手。而 SpringDataMongoDB 是 Spring 生态的一员,封装了 mongodb-driver,提供了更简洁的 API,方便开发者在 Spring 环境中操作 MongoDB。两者各有优势,可根据实际需求选择合适的技术方案。
84 2