高并发架构实践指南——应用程序演示(工程架构、开发)

我们将开发部署一套ShiponlineOrder微服务作为演示的案例。

工程架构

采用经典的三层架构:资源层、业务层、持久层

xuej@dev-server:~/Documents/sts4/microservice-standardexpress-shiponlineorder$ tree -d -I "target|test|generator|backup"
.
└── src
    └── main
        ├── java
        │   └── tech
        │       └── foolfish
        │           └── standardexpress
        │               ├── business
        │               │   └── model
        │               ├── config
        │               ├── persistence
        │               │   ├── dao
        │               │   └── model
        │               ├── resource
        │               │   └── model
        │               └── util
        └── resources
            └── META-INF
                └── xmlmappers

18 directories
xuej@dev-server:~/Documents/sts4/microservice-standardexpress-shiponlineorder$ tree -l -I "target|test|generator|backup"
.
├── HELP.md
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
    └── main
        ├── java
        │   └── tech
        │       └── foolfish
        │           └── standardexpress
        │               ├── business
        │               │   ├── model
        │               │   │   └── ShiponlineOrderDTO.java
        │               │   ├── ShiponlineOrderConverter.java
        │               │   └── ShiponlineOrderService.java
        │               ├── config
        │               │   └── WebFilter.java
        │               ├── persistence
        │               │   ├── dao
        │               │   │   └── ShiponlineOrderDao.java
        │               │   └── model
        │               │       ├── ShiponlineOrderDOExample.java
        │               │       ├── ShiponlineOrderDO.java
        │               │       └── ShiponlineOrderDOKey.java
        │               ├── resource
        │               │   ├── ApiUtil.java
        │               │   ├── model
        │               │   │   ├── ErrorParametersVO.java
        │               │   │   ├── ErrorVO.java
        │               │   │   └── ShiponlineOrderVO.java
        │               │   ├── ShiponlineApiController.java
        │               │   ├── ShiponlineApiDelegateImpl.java
        │               │   ├── ShiponlineApiDelegate.java
        │               │   ├── ShiponlineApi.java
        │               │   └── ShiponlineOrderConverter.java
        │               ├── RFC3339DateFormat.java
        │               ├── ShiponlineOrderApplication.java
        │               └── util
        │                   ├── DatePeriod.java
        │                   ├── DateTimePeriod.java
        │                   ├── DateTimeUtil.java
        │                   ├── FoolfishConstant.java
        │                   ├── IdGenerator.java
        │                   ├── OltpPageRequest.java
        │                   ├── Page.java
        │                   ├── PageUtil.java
        │                   ├── RandomUtil.java
        │                   └── ResponseUtil.java
        └── resources
            ├── application.properties
            └── META-INF
                ├── mapper-config.xml
                └── xmlmappers
                    └── ShiponlineOrderDao.xml

18 directories, 36 files

开发

技术栈:OpenAPI,Spring Boot,SpringCloud Netflix,MyBatis XML Mapper,HikariCP,ShardingSphere JDBC,ZooKeeper
配置方法:Spring Boot Starter

定义API文档

openapi: 3.0.3
info:
   title: StandardExpress Application
   description: StandardExpress Application
   contact:
      name: xuejwa
      url: http://www.foolfish.tech
      email: xuejwa@qq.com
   version: 0.0.1
servers:
-  url: http://localhost:8080/dev
   description: Dev API
tags:
-  name: Shiponline
paths:
   /shiponline/orders:
      get:
         tags:
         - Shiponline
         operationId: listShiponlineOrders
         responses:
            '200':
               description: OK
               content:
                  application/json:
                     schema:
                        type: array
                        items:
                           $ref: '#/components/schemas/ShiponlineOrder'
            '400':
               $ref: '#/components/responses/400BadRequest'
            '401':
               $ref: '#/components/responses/401Unauthorized'
            '404':
               $ref: '#/components/responses/404NotFound'
      post:
         tags:
         - Shiponline
         operationId: createShiponlineOrder
         requestBody:
            required: true
            content:
               application/json:
                  schema:
                     $ref: '#/components/schemas/ShiponlineOrder'
         responses:
            '201':
               description: Created
               content:
                  application/json:
                     schema:
                        $ref: '#/components/schemas/ShiponlineOrder'
            '400':
               $ref: '#/components/responses/400BadRequest'
            '401':
               $ref: '#/components/responses/401Unauthorized'
   /shiponline/orders/async:
      post:
         tags:
         - Shiponline
         operationId: createShiponlineOrderAsync
         requestBody:
            required: true
            content:
               application/json:
                  schema:
                     $ref: '#/components/schemas/ShiponlineOrder'
         responses:
            '200':
               $ref: '#/components/responses/200OK'
            '400':
               $ref: '#/components/responses/400BadRequest'
            '401':
               $ref: '#/components/responses/401Unauthorized'
   /shiponline/{shipper_id}/orders/{order_id}:
      parameters:
      -  name: shipper_id
         in: path
         required: true
         schema:
            type: string
      -  name: order_id
         in: path
         required: true
         schema:
            type: string
      get:
         tags:
         - Shiponline
         operationId: getShiponlineOrder
         responses:
            '200':
               description: OK
               content:
                  application/json:
                     schema:
                        $ref: '#/components/schemas/ShiponlineOrder'
            '400':
               $ref: '#/components/responses/400BadRequest'
            '401':
               $ref: '#/components/responses/401Unauthorized'
            '404':
               $ref: '#/components/responses/404NotFound'
      put:
         tags:
         - Shiponline
         operationId: updateShiponlineOrder
         requestBody:
            required: true
            content:
               application/json:
                  schema:
                     $ref: '#/components/schemas/ShiponlineOrder'
         responses:
            '200':
               description: OK
               content:
                  application/json:
                     schema:
                        $ref: '#/components/schemas/ShiponlineOrder'
            '400':
               $ref: '#/components/responses/400BadRequest'
            '401':
               $ref: '#/components/responses/401Unauthorized'
      delete:
         tags:
         - Shiponline
         operationId: deleteShiponlineOrder
         responses:
            '204':
               $ref: '#/components/responses/204NoContent'
            '400':
               $ref: '#/components/responses/400BadRequest'
            '401':
               $ref: '#/components/responses/401Unauthorized'
components:
   schemas:
      ShiponlineOrder:
         type: object
         required:
         - shipper_name
         - shipper_mobile_no
         - shipper_country
         - shipper_province
         - shipper_city
         - shipper_county
         - shipper_address
         - receiver_name
         - receiver_mobile_no
         - receiver_country
         - receiver_province
         - receiver_city
         - receiver_county
         - receiver_address
         - parcel_type
         - parcel_name
         - parcel_pieces
         - parcel_weight
         - pay_method
         - is_privacy_waybill
         - verification_code
         - estimated_freight
         - insurance_fee
         - estimated_cost
         properties:
            create_time:
               type: string
               format: date-time
               description: 创建时间
            update_time:
               type: string
               format: date-time
               description: 更新时间
            order_id:
               type: string
               maxLength: 45
               description: 订单号
            shipper_id:
               type: string
               maxLength: 32
               description: 寄件人ID
            shipper_name:
               type: string
               maxLength: 100
               description: 寄件人姓名
            shipper_mobile_no:
               type: string
               maxLength: 20
               description: 寄件人手机号
            shipper_country:
               type: string
               maxLength: 30
               description: 寄件人国家
            shipper_province:
               type: string
               maxLength: 30
               description: 寄件人省
            shipper_city:
               type: string
               maxLength: 100
               description: 寄件人市
            shipper_county:
               type: string
               maxLength: 30
               description: 寄件人区县
            shipper_address:
               type: string
               maxLength: 200
               description: 寄件人详细地址
            receiver_id:
               type: string
               maxLength: 32
               description: 收件人ID
            receiver_name:
               type: string
               maxLength: 100
               description: 收件人姓名
            receiver_mobile_no:
               type: string
               maxLength: 20
               description: 收件人手机号
            receiver_country:
               type: string
               maxLength: 30
               description: 收件人国家
            receiver_province:
               type: string
               maxLength: 30
               description: 收件人省
            receiver_city:
               type: string
               maxLength: 100
               description: 收件人市
            receiver_county:
               type: string
               maxLength: 30
               description: 收件人区县
            receiver_address:
               type: string
               maxLength: 200
               description: 收件人详细地址
            parcel_type:
               type: integer
               format: int32
               maximum: 9
               minimum: 1
               description: 物品类型;1:文件,2:数码产品,3:生活用品,4:食品,5:服饰,6:其他,7:生鲜类,8:易碎品,9:液体
            parcel_name:
               type: string
               description: 物品名称
            parcel_pieces:
               type: integer
               format: int32
               minimum: 1
               description: 物品件数
            parcel_weight:
               type: integer
               format: int32
               maximum: 30
               minimum: 1
               description: 物品重量(KG)
            pay_method:
               type: integer
               format: int32
               maximum: 2
               minimum: 1
               description: 支付方式;1:寄付现结,2:到付现结
            insurance_amount:
               type: integer
               format: int32
               maximum: 30000
               minimum: 0
               description: 保价金额(¥)
            is_privacy_waybill:
               type: boolean
               description: 是否隐私面单;启用后快递面单会对收件方的姓名电话进行隐匿处理,使用即同意《信息加密说明》
            leavemessage:
               type: string
               maxLength: 100
               minLength: 0
               description: 给小哥留言;常用留言如:请带纸箱、需爬楼、需文件袋、来前电话、我没胶带
            verification_code:
               type: string
               maxLength: 4
               minLength: 4
               description: 验证码
            estimated_freight:
               type: number
               format: double
               minimum: 0
               description: 预估运费(¥)
            insurance_fee:
               type: integer
               format: int32
               maximum: 150
               minimum: 0
               description: 保价费(¥)
            estimated_cost:
               type: number
               format: double
               minimum: 0
               description: 预估费用(¥)
         example:
            create_time: '2022-05-25T21:57:14Z'
            update_time: '2022-05-25T21:57:14Z'
            order_id: KDUtSvS0cK8mj4-JI7HgX
            shipper_name: 张三
            shipper_mobile_no: '185******72'
            shipper_country: 中国
            shipper_province: 北京市
            shipper_city: 北京市
            shipper_county: 朝阳区
            shipper_address: 绿地中心C座阿里巴巴北京总部
            receiver_name: 李四
            receiver_mobile_no: '175******45'
            receiver_country: 中国
            receiver_province: 上海市
            receiver_city: 上海市
            receiver_county: 青浦区
            receiver_address: 6666号中国速递
            parcel_type: 1
            parcel_name: 机密文件
            parcel_pieces: 1
            parcel_weight: 30
            pay_method: 1
            insurance_amount: 0
            is_privacy_waybill: true
            leavemessage: 请带纸箱
            verification_code: 8CN8
            estimated_freight: 70
            insurance_fee: 0
            estimated_cost: 100
      Error:
         type: object
         required:
         - status
         - title
         - detail
         properties:
            status:
               type: string
            title:
               type: string
            detail:
               type: string
            parameters:
               type: object
               properties:
                  path:
                     type: string
                  message:
                     type: string
                     nullable: true
                  field_errors:
                     type: string
                     nullable: true
   parameters:
      page_number:
         name: page_number
         in: query
         required: false
         schema:
            type: integer
            format: int32
            minimum: 1
            maximum: 100
            default: 1
      page_size:
         name: page_size
         in: query
         required: false
         schema:
            type: integer
            format: int32
            minimum: 20
            maximum: 100
            default: 20
      begin_date:
         name: begin_date
         in: query
         required: true
         schema:
            type: string
            format: date
      end_date:
         name: end_date
         in: query
         required: true
         schema:
            type: string
            format: date
      key_word:
         name: key_word
         in: query
         required: false
         schema:
            type: string
      is_activated:
         name: is_activated
         in: query
         required: false
         schema:
            type: boolean
            default: true
   responses:
      200OK:
         description: The request has succeeded.
         content:
            application/json: {}
      201Created:
         description: The request has succeeded and a new resource has been created as a result.
         content:
            application/json: {}
      202Accepted:
         description: The request has been received but not yet acted upon.
         content:
            application/json: {}
      204NoContent:
         description: There is no content to send for this request, but the headers may be useful.
         content:
            application/json: {}
      400BadRequest:
         description: The server could not understand the request due to invalid syntax.
         content:
            application/json:
               schema:
                  $ref: '#/components/schemas/Error'
      401Unauthorized:
         description: Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated".
         content:
            application/json:
               schema:
                  $ref: '#/components/schemas/Error'
      403Forbidden:
         description: The client does not have access rights to the content; that is, it is unauthorized, so the server is
            refusing to give the requested resource.
         content:
            application/json:
               schema:
                  $ref: '#/components/schemas/Error'
      404NotFound:
         description: The server can not find the requested resource.
         content:
            application/json:
               schema:
                  $ref: '#/components/schemas/Error'
      429TooManyRequests:
         description: The user has sent too many requests in a given amount of time ("rate limiting").
         content:
            application/json:
               schema:
                  $ref: '#/components/schemas/Error'
      500InternalServerError:
         description: The server has encountered a situation it doesn't know how to handle.
         content:
            application/json:
               schema:
                  $ref: '#/components/schemas/Error'
      502BadGateway:
         description: This error response means that the server, while working as a gateway to get a response needed to handle
            the request, got an invalid response.
         content:
            application/json:
               schema:
                  $ref: '#/components/schemas/Error'
      503ServiceUnavailable:
         description: The server is not ready to handle the request. Common causes are a server that is down for maintenance
            or that is overloaded.
         content:
            application/json:
               schema:
                  $ref: '#/components/schemas/Error'
   headers:
      X-Request-ID:
         schema:
            type: string
            example: '20200101235959123456789'
      X-Rate-Limit-Limit:
         schema:
            type: integer
            format: int32
            example: 100
      X-Rate-Limit-Remaining:
         schema:
            type: integer
            format: int32
            example: 10
      X-Rate-Limit-Reset-After:
         schema:
            type: integer
            format: int32
            example: 3600
      X-Authorization-Token:
         schema:
            type: string
            format: JWT
            example: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxODUxMDI1NDAxMiIsImF1dGgiOiJST0xFX1VTRVIiLCJleHAiOjI1OTIxNjA0MTk5Njk1fQ.b9iN-VBNU7P3MQNa-u886gjILLmIPFhSNWLW6TmPU8gkKOjDr9zqYj2izH-Aha3VpUf3owwIL8iyWdQeA7_WYg
      X-Authorization-Expires-After:
         schema:
            type: string
            format: date-time
            example: '2021-07-30T08:08:08.888Z'
      X-Pagination-TotalCount:
         schema:
            type: integer
            format: int64
            example: 10000
      X-Pagination-TotalPages:
         schema:
            type: integer
            format: int32
            example: 100
      X-Pagination-PageNumber:
         schema:
            type: integer
            format: int32
            example: 3
      X-Pagination-PageSize:
         schema:
            type: integer
            format: int32
            example: 100

定义数据库模型

-- MySQL dump 10.13  Distrib 5.7.37, for Linux (x86_64)
--
-- Host: localhost    Database: standardexpress
-- ------------------------------------------------------
-- Server version   5.7.37

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Current Database: `standardexpress`
--

/*!40000 DROP DATABASE IF EXISTS `standardexpress`*/;

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `standardexpress` /*!40100 DEFAULT CHARACTER SET latin1 */;

USE `standardexpress`;

--
-- Table structure for table `shiponline_order`
--

DROP TABLE IF EXISTS `shiponline_order`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `shiponline_order` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL COMMENT '更新时间',
  `order_id` varchar(45) NOT NULL COMMENT '客户订单号',
  `shipper_id` varchar(32) NOT NULL COMMENT '寄件人ID',
  `shipper_name` varchar(100) DEFAULT NULL COMMENT '寄件人姓名',
  `shipper_mobile_no` varchar(20) DEFAULT NULL COMMENT '寄件人手机号',
  `shipper_country` varchar(30) DEFAULT NULL COMMENT '寄件人所在国家',
  `shipper_province` varchar(30) DEFAULT NULL COMMENT '寄件人所在省',
  `shipper_city` varchar(100) DEFAULT NULL COMMENT '寄件人省所在市',
  `shipper_county` varchar(30) DEFAULT NULL COMMENT '寄件人省所在区县',
  `shipper_address` varchar(200) DEFAULT NULL COMMENT '寄件人详细地址',
  `receiver_id` varchar(32) NOT NULL COMMENT '收件人ID',
  `receiver_name` varchar(100) DEFAULT NULL COMMENT '收件人姓名',
  `receiver_mobile_no` varchar(20) DEFAULT NULL COMMENT '收件人手机号',
  `receiver_country` varchar(30) DEFAULT NULL COMMENT '收件人所在国家',
  `receiver_province` varchar(30) DEFAULT NULL COMMENT '收件人所在省',
  `receiver_city` varchar(100) DEFAULT NULL COMMENT '收件人省所在市',
  `receiver_county` varchar(30) DEFAULT NULL COMMENT '收件人省所在区县',
  `receiver_address` varchar(200) DEFAULT NULL COMMENT '收件人详细地址',
  `parcel_type` int(10) unsigned DEFAULT NULL COMMENT '物品类型',
  `parcel_name` varchar(100) DEFAULT NULL COMMENT '物品类型',
  `parcel_pieces` int(10) unsigned DEFAULT NULL COMMENT '物品件数',
  `parcel_weight` int(10) unsigned DEFAULT NULL COMMENT '物品重量',
  `pay_method` int(10) unsigned DEFAULT NULL COMMENT '支付方式',
  `insurance_amount` int(10) unsigned DEFAULT NULL COMMENT '保价金额',
  `is_privacy_waybill` tinyint(1) DEFAULT NULL COMMENT '是否隐私面单',
  `leavemessage` varchar(100) DEFAULT NULL COMMENT '给小哥留言',
  `estimated_freight` decimal(5,2) DEFAULT NULL COMMENT '预估运费',
  `insurance_fee` int(10) unsigned DEFAULT NULL COMMENT '保价费',
  `estimated_cost` decimal(5,2) DEFAULT NULL COMMENT '预估费用',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_shipper_id_order_id` (`shipper_id`,`order_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2022-07-30 17:43:16

数据库表名不能取名为order,会导致insert SQL语法错误!

Core Annotation

package tech.foolfish.standardexpress;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;

@SpringBootApplication
@EnableCircuitBreaker
public class ShiponlineOrderApplication {

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

}

application配置文件

eureka.client.fetchRegistry=true
eureka.client.registerWithEureka=true
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
#management.endpoints.web.exposure.include='*'
#management.metrics.export.prometheus.pushgateway.job=standardexpress-shiponlineorder

#server.port=8081
server.port=${random.int[32768,60999]}
server.jetty.threads.max=200

mybatis.check-config-location = true
mybatis.config-location = classpath:META-INF/mapper-config.xml

spring.application.name = standardexpress-shiponlineorder
spring.jackson.date-format = tech.foolfish.standardexpress.RFC3339DateFormat
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS = false
spring.jackson.serialization.indent-output = true

#############################################################
############### shardingsphere(5.1.1) (begin) ###############
#############################################################

########################################
########## Mode Configuration ##########
########################################

##### Memory Mode #####
#spring.shardingsphere.mode.type=Memory
spring.shardingsphere.mode.type=Cluster
spring.shardingsphere.mode.repository.type=ZooKeeper
spring.shardingsphere.mode.repository.props.namespace=demo_spring_boot_readwrite_ds
# spring.shardingsphere.mode.repository.props.server-lists=localhost:2181
spring.shardingsphere.mode.repository.props.server-lists=zk1:2181,zk2:2181,zk3:2181
spring.shardingsphere.mode.overwrite=true

#################################
########## Data Source ##########
#################################
# Configure actual data sources
spring.shardingsphere.datasource.names=ds0,ds1,ds2

spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://db1:3306/standardexpress?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=Passw0rd
spring.shardingsphere.datasource.ds0.maximum-pool-size = 10

spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://db1-repl0:3306/standardexpress?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=Passw0rd
spring.shardingsphere.datasource.ds1.maximum-pool-size = 10

spring.shardingsphere.datasource.ds2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds2.jdbc-url=jdbc:mysql://db1-repl1:3306/standardexpress?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds2.username=root
spring.shardingsphere.datasource.ds2.password=Passw0rd
spring.shardingsphere.datasource.ds2.maximum-pool-size = 10

###########################
########## Rules ##########
###########################

##### Sharding #####
# Standard sharding table configuration
#spring.shardingsphere.rules.sharding.tables.shiponline_order.actual-data-nodes=ha-rws.shiponline_order
# Databases sharding strategy

# For single sharding column scenario
#spring.shardingsphere.rules.sharding.tables.shiponline_order.database-strategy.standard.sharding-column=shipper_id
#spring.shardingsphere.rules.sharding.tables.shiponline_order.database-strategy.standard.sharding-algorithm-name=database-inline

# Tables sharding strategy
#spring.shardingsphere.rules.sharding.tables.shiponline_order.table-strategy.standard.sharding-column=order_id
#spring.shardingsphere.rules.sharding.tables.shiponline_order.table-strategy.standard.sharding-algorithm-name=shiponline-order-table-inline

# Default sharding strategy
#spring.shardingsphere.sharding.default-database-strategy.sharding-algorithm-name=database-inline
#spring.shardingsphere.sharding.default-sharding-column=shipper_id

# Sharding algorithm configuration
#spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.type=HASH_MOD
#spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.props.sharding-count=2
#spring.shardingsphere.rules.sharding.sharding-algorithms.shiponline-order-table-inline.type=HASH_MOD
#spring.shardingsphere.rules.sharding.sharding-algorithms.shiponline-order-table-inline.props.sharding-count=2

##### Dynamic Readwrite-splitting ##### 
spring.shardingsphere.rules.readwrite-splitting.data-sources.ha-rws.type= Dynamic
spring.shardingsphere.rules.readwrite-splitting.data-sources.ha-rws.props.auto-aware-data-source-name= rws-ds
spring.shardingsphere.rules.readwrite-splitting.data-sources.ha-rws.load-balancer-name= read-round-robin
#spring.shardingsphere.rules.readwrite-splitting.load-balancers.read-random.type=RANDOM
spring.shardingsphere.rules.readwrite-splitting.load-balancers.read-round-robin.type=ROUND_ROBIN

##### HA #####
spring.shardingsphere.rules.database-discovery.data-sources.rws-ds.data-source-names=ds0,ds1,ds2
spring.shardingsphere.rules.database-discovery.data-sources.rws-ds.discovery-heartbeat-name=db1-heartbeat
spring.shardingsphere.rules.database-discovery.data-sources.rws-ds.discovery-type-name=db1-mgr
spring.shardingsphere.rules.database-discovery.discovery-heartbeats.db1-heartbeat.props.keep-alive-cron=0/5 * * * * ?
spring.shardingsphere.rules.database-discovery.discovery-types.db1-mgr.type=MGR
spring.shardingsphere.rules.database-discovery.discovery-types.db1-mgr.props.group-name=62a8920f-7a88-4998-9c46-cce7b8f99cfd

### other properties ###
spring.shardingsphere.props.sql-show=true

######################################################
############### shardingsphere (end) #################
######################################################

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>tech.foolfish</groupId>
    <artifactId>standardexpress-shiponlineorder</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>microservice-standardexpress-shiponlineorder</name>
    <description>Standardexpress Shiponlineorder</description>
    <properties>
        <curator.version>5.1.0</curator.version>
        <java.version>11</java.version>
        <m2e.apt.activation>jdt_apt</m2e.apt.activation>
        <mapstruct.version>1.4.1.Final</mapstruct.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
        <shardingsphere.version>5.1.1</shardingsphere.version>
        <spring-boot.version>2.3.12.RELEASE</spring-boot.version>
        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
        <spring-cloud-netflix.version>2.2.9.RELEASE</spring-cloud-netflix.version>
        <spring-cloud-sleuth.version>2.2.8.RELEASE</spring-cloud-sleuth.version>
        <springfox-version>2.9.2</springfox-version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>${shardingsphere.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-cluster-mode-repository-zookeeper-curator
            </artifactId>
            <version>${shardingsphere.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>${curator.version}</version><!--$NO-MVN-MAN-VER$ -->
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-client</artifactId>
            <version>${curator.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>${curator.version}</version><!--$NO-MVN-MAN-VER$ -->
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-typehandlers-jsr310</artifactId>
            <version>1.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version><!--$NO-MVN-MAN-VER$ -->
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${mapstruct.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${mapstruct.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${springfox-version}</version>
        </dependency>
        <dependency>
            <groupId>org.openapitools</groupId>
            <artifactId>jackson-databind-nullable</artifactId>
            <version>0.2.1</version>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>org.zalando</groupId>
            <artifactId>problem-spring-web</artifactId>
            <version>0.26.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>com.aventrix.jnanoid</groupId>
            <artifactId>jnanoid</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${springfox-version}</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </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>
        </dependencies>
    </dependencyManagement>
    <build>
        <finalName>${project.name}</finalName>
        <defaultGoal>spring-boot:run</defaultGoal>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <executable>true</executable>
                </configuration>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>${maven-compiler-plugin.version}</version>
                    <configuration>
                        <source>${java.version}</source>
                        <target>${java.version}</target>
                        <annotationProcessorPaths>
                            <path>
                                <groupId>org.springframework.boot</groupId>
                                <artifactId>spring-boot-configuration-processor</artifactId>
                                <version>${spring-boot.version}</version>
                            </path>
                            <path>
                                <groupId>org.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>${mapstruct.version}</version>
                            </path>
                        </annotationProcessorPaths>
                        <showWarnings>true</showWarnings>
                        <compilerArgs>
                            <compilerArg>-Amapstruct.suppressGeneratorTimestamp=true
                            </compilerArg>
                            <compilerArg>-Amapstruct.suppressGeneratorVersionInfoComment=true
                            </compilerArg>
                            <compilerArg>-Amapstruct.verbose=true</compilerArg>
                            <compilerArg>-Amapstruct.defaultComponentModel=default
                            </compilerArg>
                        </compilerArgs>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>${maven-war-plugin.version}</version>
                    <executions>
                        <execution>
                            <id>default-war</id>
                            <goals>
                                <goal>war</goal>
                            </goals>
                            <phase>package</phase>
                        </execution>
                    </executions>
                    <configuration>
                        <warSourceIncludes>WEB-INF/**,META-INF/**</warSourceIncludes>
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>${maven-clean-plugin.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>${maven-resources-plugin.version}</version>
                    <executions>
                        <execution>
                            <id>default-resources</id>
                            <phase>validate</phase>
                            <goals>
                                <goal>copy-resources</goal>
                            </goals>
                            <configuration>
                                <outputDirectory>${project.build.directory}/classes
                                </outputDirectory>
                                <useDefaultDelimiters>false</useDefaultDelimiters>
                                <delimiters>
                                    <delimiter>#</delimiter>
                                </delimiters>
                                <resources>
                                    <resource>
                                        <directory>src/main/resources/</directory>
                                        <filtering>true</filtering>
                                        <includes>
                                            <include>application.yml</include>
                                            <include>application.yaml</include>
                                            <include>application.properties</include>
                                            <include>application-${spring.profiles.active}.yml</include>
                                            <include>application-${spring.profiles.active}.yaml</include>
                                            <include>application-${spring.profiles.active}.properties
                                            </include>
                                            <include>hikari.properties</include>
                                            <include>META-INF</include>
                                        </includes>
                                    </resource>
                                    <resource>
                                        <directory>src/main/resources/</directory>
                                        <filtering>false</filtering>
                                        <excludes>
                                            <exclude>*.yml</exclude>
                                            <exclude>*.yaml</exclude>
                                            <exclude>*.properties</exclude>
                                            <exclude>META-INF</exclude>
                                        </excludes>
                                    </resource>
                                </resources>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <mainClass>${start-class}</mainClass>
                        <fork>true</fork>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
    <profiles>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-devtools</artifactId>
                    <optional>true</optional>
                </dependency>
            </dependencies>
            <properties>
                <spring.profiles.active>dev</spring.profiles.active>
            </properties>
        </profile>
        <profile>
            <id>prod</id>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-clean-plugin</artifactId>
                        <configuration>
                            <filesets>
                                <fileset>
                                    <directory>target/</directory>
                                </fileset>
                            </filesets>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>build-info</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
            <properties>
                <spring.profiles.active>prod</spring.profiles.active>
            </properties>
        </profile>
        <profile>
            <id>war</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-war-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>IDE</id>
            <dependencies>
                <dependency>
                    <groupId>org.mapstruct</groupId>
                    <artifactId>mapstruct-processor</artifactId>
                </dependency>
            </dependencies>
        </profile>
    </profiles>

</project>

创建资源层

xuej@dev-server:~/Documents/sts4/microservice-standardexpress-shiponlineorder$ java -jar generator/openapi-generator-cli.jar generate -g spring -i generator/openapi.yaml -o . -c generator/openapi-generator-config.yaml --minimal-update --model-name-suffix VO --global-property apis,apiTests,models,modelTests=true
[main] INFO  o.o.codegen.DefaultGenerator - Generating with dryRun=false
[main] INFO  o.o.c.ignore.CodegenIgnoreProcessor - No .openapi-generator-ignore file found.
[main] INFO  o.o.codegen.DefaultGenerator - OpenAPI Generator: spring (server)
[main] INFO  o.o.codegen.DefaultGenerator - Generator 'spring' is considered stable.
[main] INFO  o.o.codegen.languages.SpringCodegen - ----------------------------------
[main] INFO  o.o.c.languages.AbstractJavaCodegen - Environment variable JAVA_POST_PROCESS_FILE not defined so the Java code may not be properly formatted. To define it, try 'export JAVA_POST_PROCESS_FILE="/usr/local/bin/clang-format -i"' (Linux/Mac)
[main] INFO  o.o.c.languages.AbstractJavaCodegen - NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).
[main] INFO  o.o.c.languages.AbstractJavaCodegen - Processing operation listShiponlineOrders
[main] INFO  o.o.c.languages.AbstractJavaCodegen - Processing operation createShiponlineOrder
[main] INFO  o.o.c.languages.AbstractJavaCodegen - Processing operation createShiponlineOrderAsync
[main] INFO  o.o.c.languages.AbstractJavaCodegen - Processing operation getShiponlineOrder
[main] INFO  o.o.c.languages.AbstractJavaCodegen - Processing operation updateShiponlineOrder
[main] INFO  o.o.c.languages.AbstractJavaCodegen - Processing operation deleteShiponlineOrder
[main] INFO  o.o.codegen.TemplateManager - writing file /home/xuej/Documents/sts4/microservice-standardexpress-shiponlineorder/./src/main/java/tech/foolfish/standardexpress/resource/model/ErrorParametersVO.java
[main] INFO  o.o.codegen.TemplateManager - writing file /home/xuej/Documents/sts4/microservice-standardexpress-shiponlineorder/./src/main/java/tech/foolfish/standardexpress/resource/model/ErrorVO.java
[main] INFO  o.o.codegen.TemplateManager - writing file /home/xuej/Documents/sts4/microservice-standardexpress-shiponlineorder/./src/main/java/tech/foolfish/standardexpress/resource/model/ShiponlineOrderVO.java
[main] INFO  o.o.codegen.TemplateManager - writing file /home/xuej/Documents/sts4/microservice-standardexpress-shiponlineorder/./src/main/java/tech/foolfish/standardexpress/resource/ShiponlineApiController.java
[main] INFO  o.o.codegen.TemplateManager - writing file /home/xuej/Documents/sts4/microservice-standardexpress-shiponlineorder/./src/main/java/tech/foolfish/standardexpress/resource/ShiponlineApi.java
[main] INFO  o.o.codegen.TemplateManager - writing file /home/xuej/Documents/sts4/microservice-standardexpress-shiponlineorder/./src/main/java/tech/foolfish/standardexpress/resource/ShiponlineApiDelegate.java
[main] INFO  o.o.codegen.DefaultGenerator - Skipping generation of supporting files.
################################################################################
# Thanks for using OpenAPI Generator.                                          #
# Please consider donation to help us maintain this project 🙏                 #
# https://opencollective.com/openapi_generator/donate                          #
################################################################################

ShiponlineApiDelegateImpl

package tech.foolfish.standardexpress.resource;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.NativeWebRequest;

import tech.foolfish.standardexpress.business.ShiponlineOrderService;
import tech.foolfish.standardexpress.resource.model.ShiponlineOrderVO;
import tech.foolfish.standardexpress.util.ResponseUtil;

@Component
public class ShiponlineApiDelegateImpl implements ShiponlineApiDelegate {

    private final Logger log = LoggerFactory.getLogger(ShiponlineApiDelegate.class);

    private final NativeWebRequest request;

    private final ShiponlineOrderService orderService;
    
    public ShiponlineApiDelegateImpl(NativeWebRequest request, ShiponlineOrderService orderService) {
        this.request = request;
        this.orderService = orderService;
    }

    @Override
    public Optional<NativeWebRequest> getRequest() {
        return Optional.ofNullable(request);
    }

    @Override
    public ResponseEntity<List<ShiponlineOrderVO>> listShiponlineOrders() {
        // TODO Auto-generated method stub
//      return ShiponlineApiDelegate.super.listShiponlineOrders();
        log.debug("Service layer request to list Orders");
        List<ShiponlineOrderVO> shiponlineOrderVOs = orderService.listOrders()
                .stream()
                .map(ShiponlineOrderConverter.INSTANCE::toVO)
                .collect(Collectors.toList());
        return ResponseUtil.wrapOk(shiponlineOrderVOs);
    }

    @Override
    public ResponseEntity<ShiponlineOrderVO> createShiponlineOrder(ShiponlineOrderVO orderVO) {
        log.debug("Resource layer request to create one new ShiponlineOrder: {}", orderVO);
        Optional<ShiponlineOrderVO> optionalShiponlineOrderVO = orderService.createShiponlineOrder(ShiponlineOrderConverter.INSTANCE.toDTO(orderVO))
                .map(ShiponlineOrderConverter.INSTANCE::toVO);
        return ResponseUtil.wrapCreated(optionalShiponlineOrderVO);
    }

    @Override
    public ResponseEntity<Void> createShiponlineOrderAsync(ShiponlineOrderVO shiponlineOrderVO) {
        // TODO Auto-generated method stub
        return ShiponlineApiDelegate.super.createShiponlineOrderAsync(shiponlineOrderVO);
    }

    @Override
    public ResponseEntity<ShiponlineOrderVO> getShiponlineOrder(String shipperId, String orderId) {
        log.debug("Resource layer request to get one ShiponlineOrder : {}", orderId);
        Optional<ShiponlineOrderVO> optionalShiponlineOrderVO = orderService.getShiponlineOrderByShiponlineOrderId(shipperId, orderId).map(ShiponlineOrderConverter.INSTANCE::toVO);
        return ResponseUtil.wrapOk(optionalShiponlineOrderVO);
    }

    @Override
    public ResponseEntity<ShiponlineOrderVO> updateShiponlineOrder(String shipperId, String orderId, ShiponlineOrderVO orderVO) {
        log.debug("Resource layer request to update one ShiponlineOrder of ID {}, detailed value is {}", orderId, orderVO);
        orderVO.setOrderId(orderId);
        Optional<ShiponlineOrderVO> optionalShiponlineOrderVO = orderService.updateOrderPartiallyByOrderId(ShiponlineOrderConverter.INSTANCE.toDTO(orderVO))
                .map(ShiponlineOrderConverter.INSTANCE::toVO);
        return ResponseUtil.wrapOk(optionalShiponlineOrderVO);
    }

    @Override
    public ResponseEntity<Void> deleteShiponlineOrder(String shipperId, String orderId) {
        log.debug("Resource layer request to delete Order of ID {}", orderId);
        orderService.deleteShiponlineOrderByShiponlineOrderId(shipperId, orderId);
        return ResponseUtil.wrapNoContent();
    }

}

创建持久层

xuej@dev-server:~/Documents/sts4/microservice-standardexpress-shiponlineorder$ java -cp generator/mybatis-generator-core.jar:generator/mysql-connector-java.jar org.mybatis.generator.api.ShellRunner -configfile generator/mybatis-generator-config-mybatis3.xml -overwrite -verbose
Connecting to the Database
Introspecting table shiponline_order
Generating Example class for table shiponline_order
Generating Primary Key class for table shiponline_order
Generating Record class for table shiponline_order
Generating Mapper Interface for table shiponline_order
Generating SQL Map for table shiponline_order
Saving file ShiponlineOrderDao.xml
Saving file mapper-config.xml
Saving file ShiponlineOrderDOExample.java
Saving file ShiponlineOrderDOKey.java
Saving file ShiponlineOrderDO.java
Saving file ShiponlineOrderDao.java
MyBatis Generator finished successfully.

ShiponlineOrderDao

package tech.foolfish.standardexpress.persistence.dao;

import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.session.RowBounds;
import tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDO;
import tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDOExample;
import tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDOKey;

@Mapper
public interface ShiponlineOrderDao {
    long countByExample(ShiponlineOrderDOExample example);

    int deleteByExample(ShiponlineOrderDOExample example);

    int deleteByPrimaryKey(ShiponlineOrderDOKey key);

    int insert(ShiponlineOrderDO record);

    int insertSelective(ShiponlineOrderDO record);

    List<ShiponlineOrderDO> selectByExampleWithRowbounds(ShiponlineOrderDOExample example, RowBounds rowBounds);

    List<ShiponlineOrderDO> selectByExample(ShiponlineOrderDOExample example);

    ShiponlineOrderDO selectByPrimaryKey(ShiponlineOrderDOKey key);

    int updateByExampleSelective(@Param("record") ShiponlineOrderDO record, @Param("example") ShiponlineOrderDOExample example);

    int updateByExample(@Param("record") ShiponlineOrderDO record, @Param("example") ShiponlineOrderDOExample example);

    int updateByPrimaryKeySelective(ShiponlineOrderDO record);

    int updateByPrimaryKey(ShiponlineOrderDO record);
}

ShiponlineOrderDao.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="tech.foolfish.standardexpress.persistence.dao.ShiponlineOrderDao">
  <resultMap id="BaseResultMap" type="tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDO">
    <id column="shipper_id" jdbcType="VARCHAR" property="shipperId" />
    <id column="order_id" jdbcType="VARCHAR" property="orderId" />
    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
    <result column="shipper_name" jdbcType="VARCHAR" property="shipperName" />
    <result column="shipper_mobile_no" jdbcType="VARCHAR" property="shipperMobileNo" />
    <result column="shipper_country" jdbcType="VARCHAR" property="shipperCountry" />
    <result column="shipper_province" jdbcType="VARCHAR" property="shipperProvince" />
    <result column="shipper_city" jdbcType="VARCHAR" property="shipperCity" />
    <result column="shipper_county" jdbcType="VARCHAR" property="shipperCounty" />
    <result column="shipper_address" jdbcType="VARCHAR" property="shipperAddress" />
    <result column="receiver_id" jdbcType="VARCHAR" property="receiverId" />
    <result column="receiver_name" jdbcType="VARCHAR" property="receiverName" />
    <result column="receiver_mobile_no" jdbcType="VARCHAR" property="receiverMobileNo" />
    <result column="receiver_country" jdbcType="VARCHAR" property="receiverCountry" />
    <result column="receiver_province" jdbcType="VARCHAR" property="receiverProvince" />
    <result column="receiver_city" jdbcType="VARCHAR" property="receiverCity" />
    <result column="receiver_county" jdbcType="VARCHAR" property="receiverCounty" />
    <result column="receiver_address" jdbcType="VARCHAR" property="receiverAddress" />
    <result column="parcel_type" jdbcType="INTEGER" property="parcelType" />
    <result column="parcel_name" jdbcType="VARCHAR" property="parcelName" />
    <result column="parcel_pieces" jdbcType="INTEGER" property="parcelPieces" />
    <result column="parcel_weight" jdbcType="INTEGER" property="parcelWeight" />
    <result column="pay_method" jdbcType="INTEGER" property="payMethod" />
    <result column="insurance_amount" jdbcType="INTEGER" property="insuranceAmount" />
    <result column="is_privacy_waybill" jdbcType="BOOLEAN" property="isPrivacyWaybill" />
    <result column="leavemessage" jdbcType="VARCHAR" property="leavemessage" />
    <result column="estimated_freight" jdbcType="DECIMAL" property="estimatedFreight" />
    <result column="insurance_fee" jdbcType="INTEGER" property="insuranceFee" />
    <result column="estimated_cost" jdbcType="DECIMAL" property="estimatedCost" />
  </resultMap>
  <sql id="Example_Where_Clause">
    <where>
      <foreach collection="oredCriteria" item="criteria" separator="or">
        <if test="criteria.valid">
          <trim prefix="(" prefixOverrides="and" suffix=")">
            <foreach collection="criteria.criteria" item="criterion">
              <choose>
                <when test="criterion.noValue">
                  and ${criterion.condition}
                </when>
                <when test="criterion.singleValue">
                  and ${criterion.condition} #{criterion.value}
                </when>
                <when test="criterion.betweenValue">
                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
                </when>
                <when test="criterion.listValue">
                  and ${criterion.condition}
                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
                    #{listItem}
                  </foreach>
                </when>
              </choose>
            </foreach>
          </trim>
        </if>
      </foreach>
    </where>
  </sql>
  <sql id="Update_By_Example_Where_Clause">
    <where>
      <foreach collection="example.oredCriteria" item="criteria" separator="or">
        <if test="criteria.valid">
          <trim prefix="(" prefixOverrides="and" suffix=")">
            <foreach collection="criteria.criteria" item="criterion">
              <choose>
                <when test="criterion.noValue">
                  and ${criterion.condition}
                </when>
                <when test="criterion.singleValue">
                  and ${criterion.condition} #{criterion.value}
                </when>
                <when test="criterion.betweenValue">
                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
                </when>
                <when test="criterion.listValue">
                  and ${criterion.condition}
                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
                    #{listItem}
                  </foreach>
                </when>
              </choose>
            </foreach>
          </trim>
        </if>
      </foreach>
    </where>
  </sql>
  <sql id="Base_Column_List">
    shipper_id, order_id, create_time, update_time, shipper_name, shipper_mobile_no, 
    shipper_country, shipper_province, shipper_city, shipper_county, shipper_address, 
    receiver_id, receiver_name, receiver_mobile_no, receiver_country, receiver_province, 
    receiver_city, receiver_county, receiver_address, parcel_type, parcel_name, parcel_pieces, 
    parcel_weight, pay_method, insurance_amount, is_privacy_waybill, leavemessage, estimated_freight, 
    insurance_fee, estimated_cost
  </sql>
  <select id="selectByExample" parameterType="tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDOExample" resultMap="BaseResultMap">
    select
    <if test="distinct">
      distinct
    </if>
    <include refid="Base_Column_List" />
    from shiponline_order
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
    <if test="orderByClause != null">
      order by ${orderByClause}
    </if>
  </select>
  <select id="selectByPrimaryKey" parameterType="tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDOKey" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from shiponline_order
    where shipper_id = #{shipperId,jdbcType=VARCHAR}
      and order_id = #{orderId,jdbcType=VARCHAR}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDOKey">
    delete from shiponline_order
    where shipper_id = #{shipperId,jdbcType=VARCHAR}
      and order_id = #{orderId,jdbcType=VARCHAR}
  </delete>
  <delete id="deleteByExample" parameterType="tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDOExample">
    delete from shiponline_order
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
  </delete>
  <insert id="insert" parameterType="tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDO">
    insert into shiponline_order (shipper_id, order_id, create_time, 
      update_time, shipper_name, shipper_mobile_no, 
      shipper_country, shipper_province, shipper_city, 
      shipper_county, shipper_address, receiver_id, 
      receiver_name, receiver_mobile_no, receiver_country, 
      receiver_province, receiver_city, receiver_county, 
      receiver_address, parcel_type, parcel_name, 
      parcel_pieces, parcel_weight, pay_method, 
      insurance_amount, is_privacy_waybill, leavemessage, 
      estimated_freight, insurance_fee, estimated_cost
      )
    values (#{shipperId,jdbcType=VARCHAR}, #{orderId,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}, 
      #{updateTime,jdbcType=TIMESTAMP}, #{shipperName,jdbcType=VARCHAR}, #{shipperMobileNo,jdbcType=VARCHAR}, 
      #{shipperCountry,jdbcType=VARCHAR}, #{shipperProvince,jdbcType=VARCHAR}, #{shipperCity,jdbcType=VARCHAR}, 
      #{shipperCounty,jdbcType=VARCHAR}, #{shipperAddress,jdbcType=VARCHAR}, #{receiverId,jdbcType=VARCHAR}, 
      #{receiverName,jdbcType=VARCHAR}, #{receiverMobileNo,jdbcType=VARCHAR}, #{receiverCountry,jdbcType=VARCHAR}, 
      #{receiverProvince,jdbcType=VARCHAR}, #{receiverCity,jdbcType=VARCHAR}, #{receiverCounty,jdbcType=VARCHAR}, 
      #{receiverAddress,jdbcType=VARCHAR}, #{parcelType,jdbcType=INTEGER}, #{parcelName,jdbcType=VARCHAR}, 
      #{parcelPieces,jdbcType=INTEGER}, #{parcelWeight,jdbcType=INTEGER}, #{payMethod,jdbcType=INTEGER}, 
      #{insuranceAmount,jdbcType=INTEGER}, #{isPrivacyWaybill,jdbcType=BOOLEAN}, #{leavemessage,jdbcType=VARCHAR}, 
      #{estimatedFreight,jdbcType=DECIMAL}, #{insuranceFee,jdbcType=INTEGER}, #{estimatedCost,jdbcType=DECIMAL}
      )
  </insert>
  <insert id="insertSelective" parameterType="tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDO">
    insert into shiponline_order
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="shipperId != null">
        shipper_id,
      </if>
      <if test="orderId != null">
        order_id,
      </if>
      <if test="createTime != null">
        create_time,
      </if>
      <if test="updateTime != null">
        update_time,
      </if>
      <if test="shipperName != null">
        shipper_name,
      </if>
      <if test="shipperMobileNo != null">
        shipper_mobile_no,
      </if>
      <if test="shipperCountry != null">
        shipper_country,
      </if>
      <if test="shipperProvince != null">
        shipper_province,
      </if>
      <if test="shipperCity != null">
        shipper_city,
      </if>
      <if test="shipperCounty != null">
        shipper_county,
      </if>
      <if test="shipperAddress != null">
        shipper_address,
      </if>
      <if test="receiverId != null">
        receiver_id,
      </if>
      <if test="receiverName != null">
        receiver_name,
      </if>
      <if test="receiverMobileNo != null">
        receiver_mobile_no,
      </if>
      <if test="receiverCountry != null">
        receiver_country,
      </if>
      <if test="receiverProvince != null">
        receiver_province,
      </if>
      <if test="receiverCity != null">
        receiver_city,
      </if>
      <if test="receiverCounty != null">
        receiver_county,
      </if>
      <if test="receiverAddress != null">
        receiver_address,
      </if>
      <if test="parcelType != null">
        parcel_type,
      </if>
      <if test="parcelName != null">
        parcel_name,
      </if>
      <if test="parcelPieces != null">
        parcel_pieces,
      </if>
      <if test="parcelWeight != null">
        parcel_weight,
      </if>
      <if test="payMethod != null">
        pay_method,
      </if>
      <if test="insuranceAmount != null">
        insurance_amount,
      </if>
      <if test="isPrivacyWaybill != null">
        is_privacy_waybill,
      </if>
      <if test="leavemessage != null">
        leavemessage,
      </if>
      <if test="estimatedFreight != null">
        estimated_freight,
      </if>
      <if test="insuranceFee != null">
        insurance_fee,
      </if>
      <if test="estimatedCost != null">
        estimated_cost,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="shipperId != null">
        #{shipperId,jdbcType=VARCHAR},
      </if>
      <if test="orderId != null">
        #{orderId,jdbcType=VARCHAR},
      </if>
      <if test="createTime != null">
        #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="updateTime != null">
        #{updateTime,jdbcType=TIMESTAMP},
      </if>
      <if test="shipperName != null">
        #{shipperName,jdbcType=VARCHAR},
      </if>
      <if test="shipperMobileNo != null">
        #{shipperMobileNo,jdbcType=VARCHAR},
      </if>
      <if test="shipperCountry != null">
        #{shipperCountry,jdbcType=VARCHAR},
      </if>
      <if test="shipperProvince != null">
        #{shipperProvince,jdbcType=VARCHAR},
      </if>
      <if test="shipperCity != null">
        #{shipperCity,jdbcType=VARCHAR},
      </if>
      <if test="shipperCounty != null">
        #{shipperCounty,jdbcType=VARCHAR},
      </if>
      <if test="shipperAddress != null">
        #{shipperAddress,jdbcType=VARCHAR},
      </if>
      <if test="receiverId != null">
        #{receiverId,jdbcType=VARCHAR},
      </if>
      <if test="receiverName != null">
        #{receiverName,jdbcType=VARCHAR},
      </if>
      <if test="receiverMobileNo != null">
        #{receiverMobileNo,jdbcType=VARCHAR},
      </if>
      <if test="receiverCountry != null">
        #{receiverCountry,jdbcType=VARCHAR},
      </if>
      <if test="receiverProvince != null">
        #{receiverProvince,jdbcType=VARCHAR},
      </if>
      <if test="receiverCity != null">
        #{receiverCity,jdbcType=VARCHAR},
      </if>
      <if test="receiverCounty != null">
        #{receiverCounty,jdbcType=VARCHAR},
      </if>
      <if test="receiverAddress != null">
        #{receiverAddress,jdbcType=VARCHAR},
      </if>
      <if test="parcelType != null">
        #{parcelType,jdbcType=INTEGER},
      </if>
      <if test="parcelName != null">
        #{parcelName,jdbcType=VARCHAR},
      </if>
      <if test="parcelPieces != null">
        #{parcelPieces,jdbcType=INTEGER},
      </if>
      <if test="parcelWeight != null">
        #{parcelWeight,jdbcType=INTEGER},
      </if>
      <if test="payMethod != null">
        #{payMethod,jdbcType=INTEGER},
      </if>
      <if test="insuranceAmount != null">
        #{insuranceAmount,jdbcType=INTEGER},
      </if>
      <if test="isPrivacyWaybill != null">
        #{isPrivacyWaybill,jdbcType=BOOLEAN},
      </if>
      <if test="leavemessage != null">
        #{leavemessage,jdbcType=VARCHAR},
      </if>
      <if test="estimatedFreight != null">
        #{estimatedFreight,jdbcType=DECIMAL},
      </if>
      <if test="insuranceFee != null">
        #{insuranceFee,jdbcType=INTEGER},
      </if>
      <if test="estimatedCost != null">
        #{estimatedCost,jdbcType=DECIMAL},
      </if>
    </trim>
  </insert>
  <select id="countByExample" parameterType="tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDOExample" resultType="java.lang.Long">
    select count(*) from shiponline_order
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
  </select>
  <update id="updateByExampleSelective" parameterType="map">
    update shiponline_order
    <set>
      <if test="record.shipperId != null">
        shipper_id = #{record.shipperId,jdbcType=VARCHAR},
      </if>
      <if test="record.orderId != null">
        order_id = #{record.orderId,jdbcType=VARCHAR},
      </if>
      <if test="record.createTime != null">
        create_time = #{record.createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="record.updateTime != null">
        update_time = #{record.updateTime,jdbcType=TIMESTAMP},
      </if>
      <if test="record.shipperName != null">
        shipper_name = #{record.shipperName,jdbcType=VARCHAR},
      </if>
      <if test="record.shipperMobileNo != null">
        shipper_mobile_no = #{record.shipperMobileNo,jdbcType=VARCHAR},
      </if>
      <if test="record.shipperCountry != null">
        shipper_country = #{record.shipperCountry,jdbcType=VARCHAR},
      </if>
      <if test="record.shipperProvince != null">
        shipper_province = #{record.shipperProvince,jdbcType=VARCHAR},
      </if>
      <if test="record.shipperCity != null">
        shipper_city = #{record.shipperCity,jdbcType=VARCHAR},
      </if>
      <if test="record.shipperCounty != null">
        shipper_county = #{record.shipperCounty,jdbcType=VARCHAR},
      </if>
      <if test="record.shipperAddress != null">
        shipper_address = #{record.shipperAddress,jdbcType=VARCHAR},
      </if>
      <if test="record.receiverId != null">
        receiver_id = #{record.receiverId,jdbcType=VARCHAR},
      </if>
      <if test="record.receiverName != null">
        receiver_name = #{record.receiverName,jdbcType=VARCHAR},
      </if>
      <if test="record.receiverMobileNo != null">
        receiver_mobile_no = #{record.receiverMobileNo,jdbcType=VARCHAR},
      </if>
      <if test="record.receiverCountry != null">
        receiver_country = #{record.receiverCountry,jdbcType=VARCHAR},
      </if>
      <if test="record.receiverProvince != null">
        receiver_province = #{record.receiverProvince,jdbcType=VARCHAR},
      </if>
      <if test="record.receiverCity != null">
        receiver_city = #{record.receiverCity,jdbcType=VARCHAR},
      </if>
      <if test="record.receiverCounty != null">
        receiver_county = #{record.receiverCounty,jdbcType=VARCHAR},
      </if>
      <if test="record.receiverAddress != null">
        receiver_address = #{record.receiverAddress,jdbcType=VARCHAR},
      </if>
      <if test="record.parcelType != null">
        parcel_type = #{record.parcelType,jdbcType=INTEGER},
      </if>
      <if test="record.parcelName != null">
        parcel_name = #{record.parcelName,jdbcType=VARCHAR},
      </if>
      <if test="record.parcelPieces != null">
        parcel_pieces = #{record.parcelPieces,jdbcType=INTEGER},
      </if>
      <if test="record.parcelWeight != null">
        parcel_weight = #{record.parcelWeight,jdbcType=INTEGER},
      </if>
      <if test="record.payMethod != null">
        pay_method = #{record.payMethod,jdbcType=INTEGER},
      </if>
      <if test="record.insuranceAmount != null">
        insurance_amount = #{record.insuranceAmount,jdbcType=INTEGER},
      </if>
      <if test="record.isPrivacyWaybill != null">
        is_privacy_waybill = #{record.isPrivacyWaybill,jdbcType=BOOLEAN},
      </if>
      <if test="record.leavemessage != null">
        leavemessage = #{record.leavemessage,jdbcType=VARCHAR},
      </if>
      <if test="record.estimatedFreight != null">
        estimated_freight = #{record.estimatedFreight,jdbcType=DECIMAL},
      </if>
      <if test="record.insuranceFee != null">
        insurance_fee = #{record.insuranceFee,jdbcType=INTEGER},
      </if>
      <if test="record.estimatedCost != null">
        estimated_cost = #{record.estimatedCost,jdbcType=DECIMAL},
      </if>
    </set>
    <if test="_parameter != null">
      <include refid="Update_By_Example_Where_Clause" />
    </if>
  </update>
  <update id="updateByExample" parameterType="map">
    update shiponline_order
    set shipper_id = #{record.shipperId,jdbcType=VARCHAR},
      order_id = #{record.orderId,jdbcType=VARCHAR},
      create_time = #{record.createTime,jdbcType=TIMESTAMP},
      update_time = #{record.updateTime,jdbcType=TIMESTAMP},
      shipper_name = #{record.shipperName,jdbcType=VARCHAR},
      shipper_mobile_no = #{record.shipperMobileNo,jdbcType=VARCHAR},
      shipper_country = #{record.shipperCountry,jdbcType=VARCHAR},
      shipper_province = #{record.shipperProvince,jdbcType=VARCHAR},
      shipper_city = #{record.shipperCity,jdbcType=VARCHAR},
      shipper_county = #{record.shipperCounty,jdbcType=VARCHAR},
      shipper_address = #{record.shipperAddress,jdbcType=VARCHAR},
      receiver_id = #{record.receiverId,jdbcType=VARCHAR},
      receiver_name = #{record.receiverName,jdbcType=VARCHAR},
      receiver_mobile_no = #{record.receiverMobileNo,jdbcType=VARCHAR},
      receiver_country = #{record.receiverCountry,jdbcType=VARCHAR},
      receiver_province = #{record.receiverProvince,jdbcType=VARCHAR},
      receiver_city = #{record.receiverCity,jdbcType=VARCHAR},
      receiver_county = #{record.receiverCounty,jdbcType=VARCHAR},
      receiver_address = #{record.receiverAddress,jdbcType=VARCHAR},
      parcel_type = #{record.parcelType,jdbcType=INTEGER},
      parcel_name = #{record.parcelName,jdbcType=VARCHAR},
      parcel_pieces = #{record.parcelPieces,jdbcType=INTEGER},
      parcel_weight = #{record.parcelWeight,jdbcType=INTEGER},
      pay_method = #{record.payMethod,jdbcType=INTEGER},
      insurance_amount = #{record.insuranceAmount,jdbcType=INTEGER},
      is_privacy_waybill = #{record.isPrivacyWaybill,jdbcType=BOOLEAN},
      leavemessage = #{record.leavemessage,jdbcType=VARCHAR},
      estimated_freight = #{record.estimatedFreight,jdbcType=DECIMAL},
      insurance_fee = #{record.insuranceFee,jdbcType=INTEGER},
      estimated_cost = #{record.estimatedCost,jdbcType=DECIMAL}
    <if test="_parameter != null">
      <include refid="Update_By_Example_Where_Clause" />
    </if>
  </update>
  <update id="updateByPrimaryKeySelective" parameterType="tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDO">
    update shiponline_order
    <set>
      <if test="createTime != null">
        create_time = #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="updateTime != null">
        update_time = #{updateTime,jdbcType=TIMESTAMP},
      </if>
      <if test="shipperName != null">
        shipper_name = #{shipperName,jdbcType=VARCHAR},
      </if>
      <if test="shipperMobileNo != null">
        shipper_mobile_no = #{shipperMobileNo,jdbcType=VARCHAR},
      </if>
      <if test="shipperCountry != null">
        shipper_country = #{shipperCountry,jdbcType=VARCHAR},
      </if>
      <if test="shipperProvince != null">
        shipper_province = #{shipperProvince,jdbcType=VARCHAR},
      </if>
      <if test="shipperCity != null">
        shipper_city = #{shipperCity,jdbcType=VARCHAR},
      </if>
      <if test="shipperCounty != null">
        shipper_county = #{shipperCounty,jdbcType=VARCHAR},
      </if>
      <if test="shipperAddress != null">
        shipper_address = #{shipperAddress,jdbcType=VARCHAR},
      </if>
      <if test="receiverId != null">
        receiver_id = #{receiverId,jdbcType=VARCHAR},
      </if>
      <if test="receiverName != null">
        receiver_name = #{receiverName,jdbcType=VARCHAR},
      </if>
      <if test="receiverMobileNo != null">
        receiver_mobile_no = #{receiverMobileNo,jdbcType=VARCHAR},
      </if>
      <if test="receiverCountry != null">
        receiver_country = #{receiverCountry,jdbcType=VARCHAR},
      </if>
      <if test="receiverProvince != null">
        receiver_province = #{receiverProvince,jdbcType=VARCHAR},
      </if>
      <if test="receiverCity != null">
        receiver_city = #{receiverCity,jdbcType=VARCHAR},
      </if>
      <if test="receiverCounty != null">
        receiver_county = #{receiverCounty,jdbcType=VARCHAR},
      </if>
      <if test="receiverAddress != null">
        receiver_address = #{receiverAddress,jdbcType=VARCHAR},
      </if>
      <if test="parcelType != null">
        parcel_type = #{parcelType,jdbcType=INTEGER},
      </if>
      <if test="parcelName != null">
        parcel_name = #{parcelName,jdbcType=VARCHAR},
      </if>
      <if test="parcelPieces != null">
        parcel_pieces = #{parcelPieces,jdbcType=INTEGER},
      </if>
      <if test="parcelWeight != null">
        parcel_weight = #{parcelWeight,jdbcType=INTEGER},
      </if>
      <if test="payMethod != null">
        pay_method = #{payMethod,jdbcType=INTEGER},
      </if>
      <if test="insuranceAmount != null">
        insurance_amount = #{insuranceAmount,jdbcType=INTEGER},
      </if>
      <if test="isPrivacyWaybill != null">
        is_privacy_waybill = #{isPrivacyWaybill,jdbcType=BOOLEAN},
      </if>
      <if test="leavemessage != null">
        leavemessage = #{leavemessage,jdbcType=VARCHAR},
      </if>
      <if test="estimatedFreight != null">
        estimated_freight = #{estimatedFreight,jdbcType=DECIMAL},
      </if>
      <if test="insuranceFee != null">
        insurance_fee = #{insuranceFee,jdbcType=INTEGER},
      </if>
      <if test="estimatedCost != null">
        estimated_cost = #{estimatedCost,jdbcType=DECIMAL},
      </if>
    </set>
    where shipper_id = #{shipperId,jdbcType=VARCHAR}
      and order_id = #{orderId,jdbcType=VARCHAR}
  </update>
  <update id="updateByPrimaryKey" parameterType="tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDO">
    update shiponline_order
    set create_time = #{createTime,jdbcType=TIMESTAMP},
      update_time = #{updateTime,jdbcType=TIMESTAMP},
      shipper_name = #{shipperName,jdbcType=VARCHAR},
      shipper_mobile_no = #{shipperMobileNo,jdbcType=VARCHAR},
      shipper_country = #{shipperCountry,jdbcType=VARCHAR},
      shipper_province = #{shipperProvince,jdbcType=VARCHAR},
      shipper_city = #{shipperCity,jdbcType=VARCHAR},
      shipper_county = #{shipperCounty,jdbcType=VARCHAR},
      shipper_address = #{shipperAddress,jdbcType=VARCHAR},
      receiver_id = #{receiverId,jdbcType=VARCHAR},
      receiver_name = #{receiverName,jdbcType=VARCHAR},
      receiver_mobile_no = #{receiverMobileNo,jdbcType=VARCHAR},
      receiver_country = #{receiverCountry,jdbcType=VARCHAR},
      receiver_province = #{receiverProvince,jdbcType=VARCHAR},
      receiver_city = #{receiverCity,jdbcType=VARCHAR},
      receiver_county = #{receiverCounty,jdbcType=VARCHAR},
      receiver_address = #{receiverAddress,jdbcType=VARCHAR},
      parcel_type = #{parcelType,jdbcType=INTEGER},
      parcel_name = #{parcelName,jdbcType=VARCHAR},
      parcel_pieces = #{parcelPieces,jdbcType=INTEGER},
      parcel_weight = #{parcelWeight,jdbcType=INTEGER},
      pay_method = #{payMethod,jdbcType=INTEGER},
      insurance_amount = #{insuranceAmount,jdbcType=INTEGER},
      is_privacy_waybill = #{isPrivacyWaybill,jdbcType=BOOLEAN},
      leavemessage = #{leavemessage,jdbcType=VARCHAR},
      estimated_freight = #{estimatedFreight,jdbcType=DECIMAL},
      insurance_fee = #{insuranceFee,jdbcType=INTEGER},
      estimated_cost = #{estimatedCost,jdbcType=DECIMAL}
    where shipper_id = #{shipperId,jdbcType=VARCHAR}
      and order_id = #{orderId,jdbcType=VARCHAR}
  </update>
  <select id="selectByExampleWithRowbounds" parameterType="tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDOExample" resultMap="BaseResultMap">
    select
    <if test="distinct">
      distinct
    </if>
    <include refid="Base_Column_List" />
    from shiponline_order
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
    <if test="orderByClause != null">
      order by ${orderByClause}
    </if>
  </select>
</mapper>

创建业务层

ShiponlineOrderService

package tech.foolfish.standardexpress.business;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import tech.foolfish.standardexpress.business.model.ShiponlineOrderDTO;
import tech.foolfish.standardexpress.persistence.dao.ShiponlineOrderDao;
import tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDO;
import tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDOExample;
import tech.foolfish.standardexpress.persistence.model.ShiponlineOrderDOKey;
import tech.foolfish.standardexpress.util.DateTimeUtil;
import tech.foolfish.standardexpress.util.IdGenerator;

@Service
public class ShiponlineOrderService {
    private final Logger log = LoggerFactory.getLogger(ShiponlineOrderService.class);

    private final ShiponlineOrderDao orderDao;

    public ShiponlineOrderService(ShiponlineOrderDao orderDao) {
        this.orderDao = orderDao;
    }

    public Optional<ShiponlineOrderDTO> createShiponlineOrder(ShiponlineOrderDTO oneDTO) {
        LocalDateTime now = DateTimeUtil.now();
        oneDTO.setCreateTime(now);
        oneDTO.setUpdateTime(now);
        oneDTO.setOrderId(IdGenerator.generateOrderId());
        oneDTO.setShipperId(IdGenerator.generateShipperId());
        oneDTO.setReceiverId(IdGenerator.generateReceiverId());
        ShiponlineOrderDO oneDO = ShiponlineOrderConverter.INSTANCE.toDO(oneDTO);
        int insert = orderDao.insert(oneDO);
//      if (insert == 1) {
//          return getShiponlineOrderByShiponlineOrderId(oneDO.getShipperId(), oneDO.getOrderId());
//      }
        return Optional.empty();
    }

    public Optional<ShiponlineOrderDTO> createShiponlineOrderAsync(ShiponlineOrderDTO oneDTO) {
        ShiponlineOrderDO oneDO = ShiponlineOrderConverter.INSTANCE.toDO(oneDTO);
        int insert = orderDao.insert(oneDO);
        if (insert == 1) {
            return getShiponlineOrderByShiponlineOrderId(oneDO.getShipperId(), oneDO.getOrderId());
        }
        return Optional.empty();
    }

    public Optional<ShiponlineOrderDTO> getShiponlineOrderByShiponlineOrderId(String shipperId, String orderId) {
        ShiponlineOrderDOKey shiponlineOrderDOKey = new ShiponlineOrderDOKey().withShipperId(shipperId).withOrderId(orderId);
        return Optional.ofNullable(ShiponlineOrderConverter.INSTANCE.toDTO(orderDao.selectByPrimaryKey(shiponlineOrderDOKey)));
    }

    public Optional<ShiponlineOrderDTO> updateOrderPartiallyByOrderId(ShiponlineOrderDTO oneDTO) {
        ShiponlineOrderDO oneDO = ShiponlineOrderConverter.INSTANCE.toDO(oneDTO);
        int update = orderDao.updateByPrimaryKeySelective(oneDO);
        ShiponlineOrderDOKey shiponlineOrderDOKey = new ShiponlineOrderDOKey().withShipperId(oneDO.getShipperId()).withOrderId(oneDO.getOrderId());
        return Optional.ofNullable(update == 1 ? orderDao.selectByPrimaryKey(shiponlineOrderDOKey) : null)
                .map(ShiponlineOrderConverter.INSTANCE::toDTO);
    }

    public void deleteShiponlineOrderByShiponlineOrderId(String shipperId, String orderId) {
        ShiponlineOrderDOKey shiponlineOrderDOKey = new ShiponlineOrderDOKey().withShipperId(shipperId).withOrderId(orderId);
        orderDao.deleteByPrimaryKey(shiponlineOrderDOKey);
    }

    public List<ShiponlineOrderDTO> listOrders() {
        ShiponlineOrderDOExample shiponlineOrderDOExample = new ShiponlineOrderDOExample();
        shiponlineOrderDOExample.setOrderByClause("create_time desc");
        return orderDao.selectByExampleWithRowbounds(shiponlineOrderDOExample, new RowBounds(0, 20)).stream()
                .map(ShiponlineOrderConverter.INSTANCE::toDTO).collect(Collectors.toList());
    }

}

部署

按需部署多个服务实例,构建微服务集群。

打包

启动服务

查看Eureka面板

通过Zuul Gateway查询

查看Hystrix面板

可观测

健康检查

Spring Boot Actuator

管理监控

分布式追踪

Sleuth

Zipkin面板