提交 4088d09d 编写于 作者: 小傅哥's avatar 小傅哥

feat: 连接池压测 c3p0、dbcp、hikari、no-pool

上级 0cbba8fb
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
\ No newline at end of file
此差异已折叠。
version: '3'
services:
# ab -n 1 -c 1 https://baidu.com
ApacheBench:
image: jordi/ab
# 命令执行 docker-compose up -d
version: '3.9'
services:
# MySQL 8.0.32 支持 AMD/ARM
mysql:
image: mysql:8.0.32
container_name: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
TZ: Asia/Shanghai
# MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' # 可配置无密码,注意配置 SPRING_DATASOURCE_PASSWORD=
MYSQL_ROOT_PASSWORD: 123456
MYSQL_USER: xfg
MYSQL_PASSWORD: 123456
depends_on:
- mysql-job-dbdata
ports:
- "13306:3306"
volumes:
- ./sql:/docker-entrypoint-initdb.d
volumes_from:
- mysql-job-dbdata
# 自动加载数据
mysql-job-dbdata:
image: alpine:3.18.2
container_name: mysql-job-dbdata
volumes:
- /var/lib/mysql
# ************************************************************
# Sequel Ace SQL dump
# 版本号: 20050
#
# https://sequel-ace.com/
# https://github.com/Sequel-Ace/Sequel-Ace
#
# 主机: localhost (MySQL 8.0.32)
# 数据库: road_map
# 生成时间: 2023-08-13 10:25:48 +0000
# ************************************************************
/*!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 */;
SET NAMES utf8mb4;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE='NO_AUTO_VALUE_ON_ZERO', SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
# 转储表 user_order
# ------------------------------------------------------------
CREATE database if NOT EXISTS `road_map` default character set utf8mb4 collate utf8mb4_0900_ai_ci;
use `road_map`;
DROP TABLE IF EXISTS `user_order`;
CREATE TABLE `user_order` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID;【必须保留自增ID,不要将一些有随机特性的字段值设计为主键,例如order_id,会导致innodb内部page分裂和大量随机I/O,性能下降】int 大约21亿左右,超过会报错。bigint 大约9千亿左右。',
`user_name` varchar(64) NOT NULL COMMENT '用户姓名;',
`user_id` varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户编号;',
`user_mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户电话;使用varchar(20)存储手机号,不要使用整型。手机号不会做数学计算、涉及到区号或者国家代号,可能出现+-()、支持模糊查询,例如:like“135%”',
`sku` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品编号',
`sku_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品名称',
`order_id` varchar(64) NOT NULL COMMENT '订单ID',
`quantity` int NOT NULL DEFAULT '1' COMMENT '商品数量;整形定义中不显示规定显示长度,比如使用 INT,而不使用 INT(4)',
`unit_price` decimal(10,2) NOT NULL COMMENT '商品价格;小数类型为 decimal,禁止使用 float、double',
`discount_amount` decimal(10,2) NOT NULL COMMENT '折扣金额;',
`tax` decimal(4,2) NOT NULL COMMENT '费率金额;',
`total_amount` decimal(10,2) NOT NULL COMMENT '支付金额;(商品的总金额 - 折扣) * (1 - 费率)',
`order_date` datetime NOT NULL COMMENT '订单日期;timestamp的时间范围在1970-01-01 00:00:01到2038-01-01 00:00:00之间',
`order_status` tinyint(1) NOT NULL COMMENT '订单状态;0 创建、1完成、2掉单、3关单 【不要使用 enum 要使用 tinyint 替代。0-80 范围,都可以使用 tinyint】',
`is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删单;0未删除,1已删除 【表达是否概念的字段必须使用is_】',
`uuid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '唯一索引;分布式下全局唯一,用于binlog 同步 ES 方便使用',
`ipv4` int unsigned NOT NULL DEFAULT '2130706433' COMMENT '设备地址;存储IPV4地址,通过MySQL 函数转换,inet_ntoa、inet_aton 示例;SELECT INET_ATON(‘209.207.224.40′); 3520061480 SELECT INET_NTOA(3520061480); 209.207.224.40所有字段定义为NOT NULL,并设置默认值,因为null值的字段会导致每一行都占用额外存储空间\\n数据迁移容易出错,在聚合函数计算结果偏差(如count结果不准)并且null的列使索引/索引统计/值比较都更加复杂,MySQL内部需要进行特殊处理,表中有较多空字段的时候,数据库性能下降严重。开发中null只能采用is null或is not null检索,而不能采用=、in、<、<>、!=、not in这些操作符号。如:where name!=’abc’,如果存在name为null值的记录,查询结果就不会包含name为null值的记录',
`ipv6` varbinary(16) NOT NULL COMMENT '设备地址;存储IPV6地址,VARBINARY(16) 插入:INET6_ATON(''2001:0db8:85a3:0000:0000:8a2e:0370:7334'') 查询:SELECT INET6_NTOA(ip_address) ',
`ext_data` json NOT NULL COMMENT '扩展数据;记录下单时用户的设备环境等信息(核心业务字段,要单独拆表)。【select user_name, ext_data, ext_data->>''$.device'', ext_data->>''$.device.machine'' from `user_order`;】',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uq_orderid` (`order_id`),
UNIQUE KEY `uq_uuid` (`uuid`),
KEY `idx_order_date` (`order_date`),
KEY `idx_sku_unit_price_total_amount` (`sku`,`unit_price`,`total_amount`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
LOCK TABLES `user_order` WRITE;
/*!40000 ALTER TABLE `user_order` DISABLE KEYS */;
INSERT INTO `user_order` (`id`, `user_name`, `user_id`, `user_mobile`, `sku`, `sku_name`, `order_id`, `quantity`, `unit_price`, `discount_amount`, `tax`, `total_amount`, `order_date`, `order_status`, `is_delete`, `uuid`, `ipv4`, `ipv6`, `ext_data`, `update_time`, `create_time`)
VALUES
(1,'小傅哥','U001','13512345678','SKU001','Mac Pro M2 贴膜','ORD001',2,10.99,2.00,0.50,19.48,'2023-08-12 10:00:00',0,0,'uuid001',2130706433,X'20010DB885A3000000008A2E03707334','{\"device\": {\"machine\": \"IPhone 14 Pro\", \"location\": \"shanghai\"}}','2023-08-12 10:00:00','2023-08-12 10:00:00'),
(2,'福禄娃','U002','13698765432','SKU002','IPad mini4 外套','ORD002',1,25.99,0.00,1.50,24.49,'2023-08-12 11:30:00',1,0,'uuid002',2130706433,X'20010DB885A3000000008A2E03707334','{\"device\": {\"machine\": \"PC Windows\", \"location\": \"BeiJing\"}}','2023-08-12 11:30:00','2023-08-12 11:30:00'),
(3,'拎瓢冲','U003','13755555555','SKU003','数据线','ORD003',3,9.99,1.50,0.00,26.97,'2023-08-12 13:45:00',0,0,'uuid003',2130706433,X'20010DB885A3000000008A2E03707334','{\"device\": {\"machine\": \"PC Windows\", \"location\": \"BeiJing\"}}','2023-08-12 13:45:00','2023-08-12 13:45:00'),
(4,'熏5null','U004','13812345678','SKU004','U盘','ORD004',1,15.99,0.00,0.75,15.24,'2023-08-12 14:20:00',1,0,'uuid004',2130706433,X'20010DB885A3000000008A2E03707334','{\"device\": {\"machine\": \"PC Windows\", \"location\": \"BeiJing\"}}','2023-08-12 14:20:00','2023-08-12 14:20:00'),
(5,'温柔一刀','U005','13999999999','SKU005','坐垫','ORD005',2,12.50,1.25,0.25,23.75,'2023-08-12 15:55:00',0,0,'uuid005',2130706433,X'20010DB885A3000000008A2E03707334','{\"device\": {\"machine\": \"PC Windows\", \"location\": \"BeiJing\"}}','2023-08-12 15:55:00','2023-08-12 15:55:00'),
(9,'小傅哥','U001','13512345678','SKU001','Mac Pro M2 贴膜','ORD0101',2,10.99,2.00,0.50,19.48,'2023-08-12 10:00:00',0,0,'uuid010',2130706433,X'20010DB885A3000000008A2E03707334','{\"device\": {\"machine\": \"IPhone 14 Pro\", \"location\": \"shanghai\"}}','2023-08-12 10:00:00','2023-08-12 10:00:00');
/*!40000 ALTER TABLE `user_order` ENABLE KEYS */;
UNLOCK TABLES;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_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 */;
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-connection-pool</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>xfg-dev-tech-app</module>
<module>xfg-dev-tech-infrastructure</module>
</modules>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.12</version>
<relativePath/>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- # 多数据源路由配置
# mysql 5.x driver-class-name: com.mysql.jdbc.Driver mysql-connector-java 5.1.34
# mysql 8.x driver-class-name: com.mysql.cj.jdbc.Driver mysql-connector-java 8.0.22-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.28</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<!-- Aug 04, 2021 https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 application-dbcp.yml -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.9.0</version>
</dependency>
<!-- Dec 12, 2019 https://mvnrepository.com/artifact/com.mchange/c3p0 application-c3p0.yml -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>
<!-- May 13, 2023 https://mvnrepository.com/artifact/com.alibaba/druid application-druid.yml -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.18</version>
</dependency>
<!-- Jan 10, 2022 https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.2-jre</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>xfg-dev-tech</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- 统一设定POM版本信息插件 -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.7</version>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>no-pool</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profileActive>no-pool</profileActive>
</properties>
</profile>
<profile>
<id>dbcp</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profileActive>dbcp</profileActive>
</properties>
</profile>
<profile>
<id>c3p0</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profileActive>c3p0</profileActive>
</properties>
</profile>
<profile>
<id>druid</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profileActive>druid</profileActive>
</properties>
</profile>
<profile>
<id>hikari</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profileActive>hikari</profileActive>
</properties>
</profile>
</profiles>
</project>
\ No newline at end of file
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-connection-pool</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>xfg-dev-tech-app</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- # 多数据源路由配置
# mysql 5.x driver-class-name: com.mysql.jdbc.Driver mysql-connector-java 5.1.34
# mysql 8.x driver-class-name: com.mysql.cj.jdbc.Driver mysql-connector-java 8.0.22-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-infrastructure</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<finalName>xfg-dev-tech-app</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/**</include>
</includes>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/**</include>
</includes>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<skipTests>true</skipTests>
<testFailureIgnore>false</testFailureIgnore>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>cn.bugstack.xfg.dev.tech.Application</mainClass>
<layout>JAR</layout>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package cn.bugstack.xfg.dev.tech;
import cn.bugstack.xfg.dev.tech.infrastructure.dao.IUserOrderDao;
import cn.bugstack.xfg.dev.tech.infrastructure.po.UserOrderPO;
import com.google.common.base.Stopwatch;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
@Slf4j
@SpringBootApplication
@Configurable
@RestController("mysql")
@RequestMapping("/api/mysql/")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Resource
private IUserOrderDao userOrderDao;
// 缓存数据,从库中拉取。
private List<UserOrderPO> userOrderPOList = Collections.synchronizedList(new ArrayList<>());
/**
* ab:ApacheBench工具的命令。
* -c 20:并发请求数为20,表示同时发送20个请求。
* -n 600:总请求数为60,表示发送60个请求。
* <p>
* ab -c 10 -n 50 http://127.0.0.1:8091/api/mysql/cacheData
*/
@RequestMapping(value = "cacheData", method = RequestMethod.GET)
public String cacheData() {
Long maxId = userOrderDao.queryMaxId();
long idx = new Random().nextLong() % maxId;
if (idx < 0) {
idx += maxId;
}
UserOrderPO userOrderPO = userOrderDao.selectById(idx);
userOrderPOList.add(userOrderPO);
log.info("cache 存储数据到缓存,用于查询、更新测试 count:{} ", userOrderPOList.size());
return "done! 缓存数量:" + userOrderPOList.size();
}
/**
* ab:ApacheBench工具的命令。
* -c 20:并发请求数为20,表示同时发送20个请求。
* -n 600:总请求数为60,表示发送60个请求。
* <p>
* ab -c 20 -n 1000 http://127.0.0.1:8091/api/mysql/insert
*/
@RequestMapping("insert")
public String insert() {
log.info("性能测试,insert");
UserOrderPO userOrderPO = UserOrderPO.builder()
.userName("小傅哥")
.userId("xfg" .concat(RandomStringUtils.randomNumeric(3)))
.userMobile("+86 1352140" .concat(String.format("%04d", new Random().nextInt(1000))))
.sku("13811216")
.skuName("《手写MyBatis:渐进式源码实践》")
.orderId(RandomStringUtils.randomNumeric(11))
.quantity(1)
.unitPrice(BigDecimal.valueOf(128))
.discountAmount(BigDecimal.valueOf(50))
.tax(BigDecimal.ZERO)
.totalAmount(BigDecimal.valueOf(78))
.orderDate(new Date())
.orderStatus(0)
.isDelete(0)
.uuid(UUID.randomUUID().toString().replace("-", ""))
.ipv4("127.0.0.1")
.ipv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334" .getBytes())
.extData("{\"device\": {\"machine\": \"IPhone 14 Pro\", \"location\": \"shanghai\"}}")
.build();
Stopwatch stopwatch = Stopwatch.createStarted();
userOrderDao.insert(userOrderPO);
stopwatch.stop();
log.info("性能测试,insert 耗时: {}", stopwatch);
return "done! 耗时:" + stopwatch;
}
/**
* ab:ApacheBench工具的命令。
* -c 20:并发请求数为20,表示同时发送20个请求。
* -n 600:总请求数为60,表示发送60个请求。
* <p>
* ab -c 20 -n 10 http://127.0.0.1:8091/api/mysql/updateOrderStatusByUserId
*/
@RequestMapping("updateOrderStatusByUserId")
public String updateOrderStatusByUserId() {
log.info("性能测试,update");
UserOrderPO userOrderPO = userOrderPOList.remove(0);
Stopwatch stopwatch = Stopwatch.createStarted();
userOrderDao.updateOrderStatusByUserId(userOrderPO.getUserId());
stopwatch.stop();
log.info("性能测试,updateOrderStatusByUserMobile userId:{} 耗时: {}", userOrderPO.getUserId(), stopwatch);
return "done! 耗时:" + stopwatch;
}
/**
* ab:ApacheBench工具的命令。
* -c 20:并发请求数为20,表示同时发送20个请求。
* -n 600:总请求数为60,表示发送60个请求。
* <p>
* ab -c 5 -n 10 http://127.0.0.1:8091/api/mysql/updateOrderStatusByUserMobile
*/
@RequestMapping("updateOrderStatusByUserMobile")
public String updateOrderStatusByUserMobile() {
log.info("性能测试,update");
UserOrderPO userOrderPO = userOrderPOList.remove(0);
Stopwatch stopwatch = Stopwatch.createStarted();
userOrderDao.updateOrderStatusByUserMobile(userOrderPO.getUserMobile());
stopwatch.stop();
log.info("性能测试,updateOrderStatusByUserMobile userMobile:{} 耗时: {}", userOrderPO.getUserMobile(), stopwatch);
return "done! 耗时:" + stopwatch;
}
/**
* ab:ApacheBench工具的命令。
* -c 20:并发请求数为20,表示同时发送20个请求。
* -n 600:总请求数为60,表示发送60个请求。
* <p>
* ab -c 10 -n 10 http://127.0.0.1:8091/api/mysql/updateOrderStatusByOrderId
*/
@RequestMapping("updateOrderStatusByOrderId")
public String updateOrderStatusByOrderId() {
log.info("性能测试,update");
UserOrderPO userOrderPO = userOrderPOList.remove(0);
Stopwatch stopwatch = Stopwatch.createStarted();
userOrderDao.updateOrderStatusByOrderId(userOrderPO.getOrderId());
stopwatch.stop();
log.info("性能测试,updateOrderStatusByOrderId orderId:{} 耗时: {}", userOrderPO.getOrderId(), stopwatch);
return "done! 耗时:" + stopwatch;
}
/**
* ab:ApacheBench工具的命令。
* -c 20:并发请求数为20,表示同时发送20个请求。
* -n 600:总请求数为60,表示发送60个请求。
* <p>
* ab -c 1 -n 1 http://127.0.0.1:8091/api/mysql/selectByUserId
*/
@RequestMapping("selectByUserId")
public String selectByUserId() {
log.info("性能测试,update");
UserOrderPO userOrderPO = userOrderPOList.remove(0);
Stopwatch stopwatch = Stopwatch.createStarted();
userOrderDao.selectByUserId(userOrderPO.getOrderId());
stopwatch.stop();
log.info("性能测试,selectByUserId orderId:{} 耗时: {}", userOrderPO.getOrderId(), stopwatch);
return "done! 耗时:" + stopwatch;
}
/**
* ab:ApacheBench工具的命令。
* -c 20:并发请求数为20,表示同时发送20个请求。
* -n 600:总请求数为60,表示发送60个请求。
* <p>
* ab -c 20 -n 50 http://127.0.0.1:8091/api/mysql/selectByUserMobile
*/
@RequestMapping("selectByUserMobile")
public String selectByUserMobile() {
log.info("性能测试,selectByUserMobile");
UserOrderPO userOrderPO = userOrderPOList.remove(0);
Stopwatch stopwatch = Stopwatch.createStarted();
userOrderDao.selectByUserMobile(userOrderPO.getUserMobile());
stopwatch.stop();
log.info("性能测试,selectByUserMobile userMobile:{} 耗时: {}", userOrderPO.getUserMobile(), stopwatch);
return "done! 耗时:" + stopwatch;
}
/**
* ab:ApacheBench工具的命令。
* -c 20:并发请求数为20,表示同时发送20个请求。
* -n 600:总请求数为60,表示发送60个请求。
* <p>
* ab -c 20 -n 50 http://127.0.0.1:8091/api/mysql/selectByOrderId
*/
@RequestMapping("selectByOrderId")
public String selectByOrderId() {
log.info("性能测试,selectByOrderId");
UserOrderPO userOrderPO = userOrderPOList.remove(0);
Stopwatch stopwatch = Stopwatch.createStarted();
userOrderDao.selectByOrderId(userOrderPO.getOrderId());
stopwatch.stop();
log.info("性能测试,selectByOrderId orderId:{} 耗时: {}", userOrderPO.getOrderId(), stopwatch);
return "done! 耗时:" + stopwatch;
}
/**
* ab:ApacheBench工具的命令。
* -c 20:并发请求数为20,表示同时发送20个请求。
* -n 600:总请求数为60,表示发送60个请求。
* <p>
* ab -c 20 -n 500 http://127.0.0.1:8091/api/mysql/selectByOrderIdAndUserId
*/
@RequestMapping("selectByOrderIdAndUserId")
public String selectByOrderIdAndUserId() {
log.info("性能测试,selectByOrderIdAndUserId");
UserOrderPO userOrderPO = userOrderPOList.remove(0);
Stopwatch stopwatch = Stopwatch.createStarted();
userOrderDao.selectByOrderIdAndUserId(userOrderPO);
stopwatch.stop();
log.info("性能测试,selectByOrderIdAndUserId orderId:{} userId:{} 耗时: {}", userOrderPO.getOrderId(), userOrderPO.getUserId(), stopwatch);
return "done! 耗时:" + stopwatch;
}
/**
* ab:ApacheBench工具的命令。
* -c 20:并发请求数为20,表示同时发送20个请求。
* -n 600:总请求数为60,表示发送60个请求。
* <p>
* ab -c 20 -n 50 http://127.0.0.1:8091/api/mysql/selectByUserIdAndOrderId
*/
@RequestMapping("selectByUserIdAndOrderId")
public String selectByUserIdAndOrderId() {
log.info("性能测试,selectByUserIdAndOrderId");
UserOrderPO userOrderPO = userOrderPOList.remove(0);
Stopwatch stopwatch = Stopwatch.createStarted();
userOrderDao.selectByUserIdAndOrderId(userOrderPO);
stopwatch.stop();
log.info("性能测试,selectByUserIdAndOrderId userId:{} orderId:{} 耗时: {}", userOrderPO.getUserId(), userOrderPO.getOrderId(), stopwatch);
return "done! 耗时:" + stopwatch;
}
}
server:
port: 8091
spring:
datasource:
url: jdbc:mysql://127.0.0.1:13306/road_map?useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.mchange.v2.c3p0.ComboPooledDataSource
initialPoolSize: 5
minPoolSize: 5
maxPoolSize: 20
maxIdleTime: 1800
acquireIncrement: 5
idleConnectionTestPeriod: 60
testConnectionOnCheckout: true
preferredTestQuery: SELECT 1
checkoutTimeout: 5000
mybatis:
mapper-locations: classpath:/mybatis/mapper/*.xml
config-location: classpath:/mybatis/config/mybatis-config.xml
# 日志
logging:
level:
root: info
config: classpath:logback-spring.xml
\ No newline at end of file
server:
port: 8091
spring:
datasource:
url: jdbc:mysql://127.0.0.1:13306/road_map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: org.apache.commons.dbcp2.BasicDataSource
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat
mybatis:
mapper-locations: classpath:/mybatis/mapper/*.xml
config-location: classpath:/mybatis/config/mybatis-config.xml
# 日志
logging:
level:
root: info
config: classpath:logback-spring.xml
\ No newline at end of file
server:
port: 8091
spring:
datasource:
url: jdbc:mysql://localhost:13306/road_map?useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
initial-size: 5
min-idle: 5
max-active: 20
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
filters: stat,wall,log4j2
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
mybatis:
mapper-locations: classpath:/mybatis/mapper/*.xml
config-location: classpath:/mybatis/config/mybatis-config.xml
# 日志
logging:
level:
root: info
config: classpath:logback-spring.xml
\ No newline at end of file
server:
port: 8091
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:13306/road_map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
driver-class-name: com.mysql.cj.jdbc.Driver
# SpringBoot 默认配置的连接池 Hikari 可以不用指定,这里指定只是想告诉它是通过哪个数据源实例化的
type: com.zaxxer.hikari.HikariDataSource
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat
mybatis:
mapper-locations: classpath:/mybatis/mapper/*.xml
config-location: classpath:/mybatis/config/mybatis-config.xml
# 日志
logging:
level:
root: info
config: classpath:logback-spring.xml
\ No newline at end of file
server:
port: 8091
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:13306/road_map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
driver-class-name: com.mysql.cj.jdbc.Driver
type: org.springframework.jdbc.datasource.DriverManagerDataSource
mybatis:
mapper-locations: classpath:/mybatis/mapper/*.xml
config-location: classpath:/mybatis/config/mybatis-config.xml
# 日志
logging:
level:
root: info
config: classpath:logback-spring.xml
\ No newline at end of file
spring:
config:
name: xfg-dev-tech
profiles:
active: c3p0
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<configuration scan="true" scanPeriod="10 seconds">
<contextName>logback</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<springProperty scope="context" name="log.path" source="logging.path"/>
<!-- 日志格式 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 输出到控制台 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!-- 此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
<encoder>
<pattern>%d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--输出到文件-->
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>./data/log/log_info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>./data/log/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>./data/log/log_error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>./data/log/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 日志文件保留天数【根据服务器预留,可自行调整】 -->
<maxHistory>7</maxHistory>
<totalSizeCap>5GB</totalSizeCap>
</rollingPolicy>
<!-- WARN 级别及以上 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
</appender>
<!-- 异步输出 -->
<appender name="ASYNC_FILE_INFO" class="ch.qos.logback.classic.AsyncAppender">
<!-- 队列剩余容量小于discardingThreshold,则会丢弃TRACT、DEBUG、INFO级别的日志;默认值-1,为queueSize的20%;0不丢失日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>8192</queueSize>
<!-- neverBlock:true 会丢失日志,但业务性能不受影响 -->
<neverBlock>true</neverBlock>
<!--是否提取调用者数据-->
<includeCallerData>false</includeCallerData>
<appender-ref ref="INFO_FILE"/>
</appender>
<appender name="ASYNC_FILE_ERROR" class="ch.qos.logback.classic.AsyncAppender">
<!-- 队列剩余容量小于discardingThreshold,则会丢弃TRACT、DEBUG、INFO级别的日志;默认值-1,为queueSize的20%;0不丢失日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>1024</queueSize>
<!-- neverBlock:true 会丢失日志,但业务性能不受影响 -->
<neverBlock>true</neverBlock>
<!--是否提取调用者数据-->
<includeCallerData>false</includeCallerData>
<appender-ref ref="ERROR_FILE"/>
</appender>
<!-- 开发环境:控制台打印 -->
<springProfile name="dev">
<logger name="com.nmys.view" level="debug"/>
</springProfile>
<root level="info">
<appender-ref ref="CONSOLE"/>
<!-- 异步日志-INFO -->
<appender-ref ref="ASYNC_FILE_INFO"/>
<!-- 异步日志-ERROR -->
<appender-ref ref="ASYNC_FILE_ERROR"/>
</root>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 暂时未使用 文档:https://mybatis.org/mybatis-3/zh/configuration.html#typeAliases -->
<typeAliases>
</typeAliases>
</configuration>
\ No newline at end of file
<?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="cn.bugstack.xfg.dev.tech.infrastructure.dao.IUserOrderDao">
<resultMap id="dataMap" type="cn.bugstack.xfg.dev.tech.infrastructure.po.UserOrderPO">
<id column="id" property="id"/>
<result column="user_name" property="userName"/>
<result column="user_id" property="userId"/>
<result column="user_mobile" property="userMobile"/>
<result column="sku" property="sku"/>
<result column="sku_name" property="skuName"/>
<result column="order_id" property="orderId"/>
<result column="quantity" property="quantity"/>
<result column="unit_price" property="unitPrice"/>
<result column="discount_amount" property="discountAmount"/>
<result column="tax" property="tax"/>
<result column="total_amount" property="totalAmount"/>
<result column="order_date" property="orderDate"/>
<result column="order_status" property="orderStatus"/>
<result column="is_delete" property="isDelete"/>
<result column="uuid" property="uuid"/>
<result column="ipv4" property="ipv4"/>
<result column="ipv6" property="ipv6"/>
<result column="ext_data" property="extData"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<select id="insert" parameterType="cn.bugstack.xfg.dev.tech.infrastructure.po.UserOrderPO">
INSERT INTO user_order (user_name, user_id, user_mobile, sku, sku_name,
order_id, quantity, unit_price, discount_amount, tax,
total_amount, order_date, order_status, is_delete, uuid,
ipv4, ipv6, ext_data, update_time, create_time)
VALUES (#{userName}, #{userId}, #{userMobile}, #{sku}, #{skuName},
#{orderId}, #{quantity}, #{unitPrice}, #{discountAmount}, #{tax},
#{totalAmount}, #{orderDate}, #{orderStatus}, #{isDelete}, #{uuid},
INET_ATON(#{ipv4}), INET6_ATON(#{ipv6}), #{extData}, now(), now())
</select>
<update id="updateOrderStatusByUserMobile" parameterType="java.lang.String">
UPDATE user_order SET order_status = 2 WHERE user_mobile = #{userMobile}
</update>
<update id="updateOrderStatusByUserId" parameterType="java.lang.String">
UPDATE user_order SET order_status = 1 WHERE user_id = #{userId}
</update>
<update id="updateOrderStatusByOrderId" parameterType="java.lang.String">
UPDATE user_order SET order_status = 1 WHERE order_id = #{orderId}
</update>
<select id="queryMaxId" resultType="java.lang.Long">
SELECT max(id) FROM user_order
</select>
<select id="selectById" parameterType="java.lang.Long" resultMap="dataMap">
SELECT id, user_name, user_id, user_mobile, sku, sku_name,
order_id, quantity, unit_price, discount_amount, tax,
total_amount, order_date, order_status, is_delete, uuid,
ipv4, ipv6, ext_data, update_time, create_time
FROM user_order
WHERE id = #{id}
</select>
<select id="selectByUserId" parameterType="java.lang.String" resultMap="dataMap">
SELECT id, user_name, user_id, user_mobile, sku, sku_name,
order_id, quantity, unit_price, discount_amount, tax,
total_amount, order_date, order_status, is_delete, uuid,
ipv4, ipv6, ext_data, update_time, create_time
FROM user_order
WHERE user_id = #{userId}
</select>
<select id="selectByUserMobile" parameterType="java.lang.String" resultMap="dataMap">
SELECT id, user_name, user_id, user_mobile, sku, sku_name,
order_id, quantity, unit_price, discount_amount, tax,
total_amount, order_date, order_status, is_delete, uuid,
ipv4, ipv6, ext_data, update_time, create_time
FROM user_order
WHERE user_mobile = #{userMobile}
</select>
<select id="selectByOrderId" parameterType="cn.bugstack.xfg.dev.tech.infrastructure.po.UserOrderPO"
resultMap="dataMap">
SELECT id, user_name, user_id, user_mobile, sku, sku_name,
order_id, quantity, unit_price, discount_amount, tax,
total_amount, order_date, order_status, is_delete, uuid,
ipv4, ipv6, ext_data, update_time, create_time
FROM user_order
WHERE order_id = #{orderId}
</select>
<select id="selectByOrderIdAndUserId" parameterType="cn.bugstack.xfg.dev.tech.infrastructure.po.UserOrderPO"
resultMap="dataMap">
SELECT id, user_name, user_id, user_mobile, sku, sku_name,
order_id, quantity, unit_price, discount_amount, tax,
total_amount, order_date, order_status, is_delete, uuid,
ipv4, ipv6, ext_data, update_time, create_time
FROM user_order
WHERE order_id = #{orderId} and user_id = #{userId}
</select>
<select id="selectByUserIdAndOrderId" parameterType="cn.bugstack.xfg.dev.tech.infrastructure.po.UserOrderPO"
resultMap="dataMap">
SELECT id, user_name, user_id, user_mobile, sku, sku_name,
order_id, quantity, unit_price, discount_amount, tax,
total_amount, order_date, order_status, is_delete, uuid,
ipv4, ipv6, ext_data, update_time, create_time
FROM user_order
WHERE user_id = #{userId} and order_id = #{orderId}
</select>
</mapper>
package cn.bugstack.xfg.dev.tech.test;
import cn.bugstack.xfg.dev.tech.infrastructure.dao.IUserOrderDao;
import cn.bugstack.xfg.dev.tech.infrastructure.po.UserOrderPO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.UUID;
/**
* https://www.jianshu.com/p/ff412dfd852f
* https://httpd.apache.org/docs/2.4/programs/ab.html
*/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApiTest {
@Resource
private IUserOrderDao userOrderDao;
@Value("${spring.datasource.type}")
private String dataSourceType;
@Test
public void test_insert() {
for (int i = 0; i < 1; i++) {
UserOrderPO userOrderPO = UserOrderPO.builder()
.userName("小傅哥")
.userId("xfg" .concat(RandomStringUtils.randomNumeric(3)))
.userMobile("+86 13521408***")
.sku("13811216")
.skuName("《手写MyBatis:渐进式源码实践》")
.orderId(RandomStringUtils.randomNumeric(11))
.quantity(1)
.unitPrice(BigDecimal.valueOf(128))
.discountAmount(BigDecimal.valueOf(50))
.tax(BigDecimal.ZERO)
.totalAmount(BigDecimal.valueOf(78))
.orderDate(new Date())
.orderStatus(0)
.isDelete(0)
.uuid(UUID.randomUUID().toString().replace("-", ""))
.ipv4("127.0.0.1")
.ipv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334" .getBytes())
.extData("{\"device\": {\"machine\": \"IPhone 14 Pro\", \"location\": \"shanghai\"}}")
.build();
userOrderDao.insert(userOrderPO);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册