国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

spring boot集成mybatis-plus——Mybatis Plus 批量 Insert_新增數(shù)據(jù)(圖文講解)

這篇具有很好參考價值的文章主要介紹了spring boot集成mybatis-plus——Mybatis Plus 批量 Insert_新增數(shù)據(jù)(圖文講解)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Mybatis Plus 批量 Insert_新增數(shù)據(jù)(圖文講解)

?更新時間 2023-01-10 16:02:58

前言

大家好,我是小哈。

本小節(jié)中,我們將學(xué)習(xí)如何通過 Mybatis Plus 實現(xiàn) MySQL 批量插入數(shù)據(jù)。

什么是批量插入?優(yōu)勢在哪里?

先拋出一個問題:假設(shè)老板給你下了個任務(wù),向數(shù)據(jù)庫中添加 100 萬條數(shù)據(jù),并且不能耗時太久!

通常來說,我們向 MySQL 中新增一條記錄,SQL 語句類似如下:

INSERT INTO `t_user` (`name`, `age`, `gender`) VALUES ('犬小哈0', 0, 1); 

如果你需要添加 100 萬條數(shù)據(jù),就需要多次執(zhí)行此語句,這就意味著頻繁地與數(shù)據(jù)庫建立鏈接,必然導(dǎo)致網(wǎng)絡(luò) IO 開銷巨大,并且每一次數(shù)據(jù)庫執(zhí)行 SQL 都需要進行解析、優(yōu)化等操作。

幸運的是,MySQL 支持一條 SQL 語句可以批量插入多條記錄,格式如下:

INSERT INTO `t_user` (`name`, `age`, `gender`) VALUES ('犬小哈0', 0, 1), ('犬小哈1', 0, 1), ('犬小哈3', 0, 1); 

和常規(guī)的?INSERT?語句不同的是,VALUES?支持多條記錄,通過?,?逗號隔開。這樣,可以實現(xiàn)一次性插入多條記錄。

數(shù)據(jù)量不多的情況下,常規(guī)?INSERT?和批量插入性能差距不大,但是,一旦數(shù)量級上去后,執(zhí)行耗時差距就拉開了,在后面我們會實測一下它們之間的耗時對比。

表與實體類

先創(chuàng)建一個測試表?t_user, 執(zhí)行腳本如下:

DROP TABLE IF EXISTS user; CREATE TABLE `t_user` ( `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵ID', `name` varchar(30) NOT NULL DEFAULT '' COMMENT '姓名', `age` int(11) NULL DEFAULT NULL COMMENT '年齡', `gender` tinyint(2) NOT NULL DEFAULT 0 COMMENT '性別,0:女 1:男', PRIMARY KEY (`id`) ) COMMENT = '用戶表'; 

再定義一個名為?User?實體類:

/**
 * @author: 犬小哈
 * @from: 公眾號:小哈學(xué)Java, 網(wǎng)站:www.quanxiaoha.com
 * @date: 2022-12-13 14:13
 * @version: v1.0.0 * @description: TODO **/ @Data @TableName("t_user") public class User { /** * 主鍵 ID, @TableId 注解定義字段為表的主鍵,type 表示主鍵類型,IdType.AUTO 表示隨著數(shù)據(jù)庫 ID 自增 */ @TableId(type = IdType.AUTO) private Long id; /** * 姓名 */ private String name; /** * 年齡 */ private Integer age; /** * 性別 */ private Integer gender; } 

TIP:?@Data?是 Lombok 注解,偷懶用的,加上它即可免寫繁雜的?getXXX/setXXX?相關(guān)方法,不了解的小伙伴可自行搜索一下如何使用。

Mybatis Plus 偽批量插入

在前面《新增數(shù)據(jù)》?小節(jié)中,我們已經(jīng)知道了 Mybatis Plus 內(nèi)部封裝的批量插入?savaBatch()?是個假的批量插入,示例代碼如下:

List<User> users =new ArrayList<>();
for (int i = 0; i < 5; i++) { User user = new User(); user.setName("犬小哈" + i); user.setAge(i); user.setGender(1); users.add(user); } // 批量插入 boolean isSuccess = userService.saveBatch(users); System.out.println("isSuccess:" + isSuccess); 

通過打印實際執(zhí)行 SQL , 我們發(fā)現(xiàn)還是一條一條的執(zhí)行?INSERT:

mybatisplus批量新增數(shù)據(jù),mybatis,spring boot,mysql,java,數(shù)據(jù)庫

并且還帶著大家看了內(nèi)部實現(xiàn)的源碼,這種方式比起自己?for?循環(huán)一條一條?INSERT?插入數(shù)據(jù)性能要更高,原因是在會話這塊做了優(yōu)化,雖然實際執(zhí)行并不是真的批量插入。

利用 SQL 注入器實現(xiàn)真的批量插入

接下來,小哈就手把手帶你通過 Mybatis Plus 框架的 SQL 注入器實現(xiàn)一個真的批量插入。

示例項目結(jié)構(gòu)

先貼一張示例項目的結(jié)構(gòu):

mybatisplus批量新增數(shù)據(jù),mybatis,spring boot,mysql,java,數(shù)據(jù)庫

注意看我紅線標注的部分,主要關(guān)注這 4 個類與接口。

新建批量插入 SQL 注入器

在工程?config?目錄下創(chuàng)建一個 SQL 注入器?InsertBatchSqlInjector?:

/**
 * @author: 犬小哈
 * @from: 公眾號:小哈學(xué)Java, 網(wǎng)站:www.quanxiaoha.com
 * @date: 2023-01-05 14:42
 * @version: v1.0.0 * @description: 批量插入 SQL 注入器 **/ public class InsertBatchSqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) { // super.getMethodList() 保留 Mybatis Plus 自帶的方法 List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo); // 添加自定義方法:批量插入,方法名為 insertBatchSomeColumn methodList.add(new InsertBatchSomeColumn()); return methodList; } } 
說說 InsertBatchSomeColumn

InsertBatchSomeColumn?是 Mybatis Plus 內(nèi)部提供的默認批量插入,只不過這個方法作者只在 MySQL 數(shù)據(jù)測試過,所以沒有將它作為通用方法供外部調(diào)用,注意看注釋:

mybatisplus批量新增數(shù)據(jù),mybatis,spring boot,mysql,java,數(shù)據(jù)庫

源碼復(fù)制出來,如下:

/**
 * 批量新增數(shù)據(jù),自選字段 insert
 * <p> 不同的數(shù)據(jù)庫支持度不一樣!!!  只在 mysql 下測試過!!!  只在 mysql 下測試過!!!  只在 mysql 下測試過!!! </p>
 * <p> 除了主鍵是 <strong> 數(shù)據(jù)庫自增的未測試 </strong> 外理論上都可以使用!!! </p>
 * <p> 如果你使用自增有報錯或主鍵值無法回寫到entity,就不要跑來問為什么了,因為我也不知道!!! </p>
 * <p>
 * 自己的通用 mapper 如下使用:
 * <pre>
 * int insertBatchSomeColumn(List<T> entityList);
 * </pre>
 * </p>
 *
 * <li> 注意: 這是自選字段 insert !!,如果個別字段在 entity 里為 null 但是數(shù)據(jù)庫中有配置默認值, insert 后數(shù)據(jù)庫字段是為 null 而不是默認值 </li>
 *
 * <p>
 * 常用的 {@link Predicate}:
 * </p>
 *
 * <li> 例1: t -> !t.isLogicDelete() , 表示不要邏輯刪除字段 </li>
 * <li> 例2: t -> !t.getProperty().equals("version") , 表示不要字段名為 version 的字段 </li>
 * <li> 例3: t -> t.getFieldFill() != FieldFill.UPDATE) , 表示不要填充策略為 UPDATE 的字段 </li>
 *
 * @author miemie
 * @since 2018-11-29
 */

@SuppressWarnings("serial") public class InsertBatchSomeColumn extends AbstractMethod { /** * 字段篩選條件 */ @Setter @Accessors(chain = true) private Predicate<TableFieldInfo> predicate; /** * 默認方法名 */ public InsertBatchSomeColumn() { // 方法名 super("insertBatchSomeColumn"); } /** * 默認方法名 * * @param predicate 字段篩選條件 */ public InsertBatchSomeColumn(Predicate<TableFieldInfo> predicate) { super("insertBatchSomeColumn"); this.predicate = predicate; } /** * @param name 方法名 * @param predicate 字段篩選條件 * @since 3.5.0 */ public InsertBatchSomeColumn(String name, Predicate<TableFieldInfo> predicate) { super(name); this.predicate = predicate; } @SuppressWarnings("Duplicates") @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE; SqlMethod sqlMethod = SqlMethod.INSERT_ONE; List<TableFieldInfo> fieldList = tableInfo.getFieldList(); String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(true, false) + this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY); String columnScript = LEFT_BRACKET + insertSqlColumn.substring(0, insertSqlColumn.length() - 1) + RIGHT_BRACKET; String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(true, ENTITY_DOT, false) + this.filterTableFieldInfo(fieldList, predicate, i -> i.getInsertSqlProperty(ENTITY_DOT), EMPTY); insertSqlProperty = LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET; String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, ENTITY, COMMA); String keyProperty = null; String keyColumn = null; // 表包含主鍵處理邏輯,如果不包含主鍵當普通字段處理 if (tableInfo.havePK()) { if (tableInfo.getIdType() == IdType.AUTO) { /* 自增主鍵 */ keyGenerator = Jdbc3KeyGenerator.INSTANCE; keyProperty = tableInfo.getKeyProperty(); keyColumn = tableInfo.getKeyColumn(); } else { if (null != tableInfo.getKeySequence()) { keyGenerator = TableInfoHelper.genKeyGenerator(this.methodName, tableInfo, builderAssistant); keyProperty = tableInfo.getKeyProperty(); keyColumn = tableInfo.getKeyColumn(); } } } String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn); } } 

配置 SQL 注入器

在?config?包下創(chuàng)建?MybatisPlusConfig?配置類:

/**
 * @Author: 犬小哈
 * @From: 公眾號:小哈學(xué)Java, 網(wǎng)站:www.quanxiaoha.com
 * @Date: 2022-12-15 18:29
 * @Version: v1.0.0 * @Description: TODO **/ @Configuration @MapperScan("com.quanxiaoha.mybatisplusdemo.mapper") public class MybatisPlusConfig { /** * 自定義批量插入 SQL 注入器 */ @Bean public InsertBatchSqlInjector insertBatchSqlInjector() { return new InsertBatchSqlInjector(); } } 

新建 MyBaseMapper

在?config?包下創(chuàng)建?MyBaseMapper?接口,讓其繼承自 Mybatis Plus 提供的?BaseMapper, 并定義批量插入方法:

/**
 * @author: 犬小哈
 * @from: 公眾號:小哈學(xué)Java, 網(wǎng)站:www.quanxiaoha.com
 * @date: 2022-12-13 14:13
 * @version: v1.0.0 * @description: TODO **/ public interface MyBaseMapper<T> extends BaseMapper<T> { // 批量插入 int insertBatchSomeColumn(@Param("list") List<T> batchList); } 

注意:方法名必須為?insertBatchSomeColumn, 和?InsertBatchSomeColumn?內(nèi)部定義好的方法名保持一致。

新建 UserMapper

在?mapper?包下創(chuàng)建?UserMapper?接口,注意繼承剛剛自定義的?MyBaseMapper, 而不是?BaseMapper?:

/**
 * @author: 犬小哈
 * @from: 公眾號:小哈學(xué)Java, 網(wǎng)站:www.quanxiaoha.com
 * @date: 2022-12-13 14:13
 * @version: v1.0.0 * @description: TODO **/ public interface UserMapper extends MyBaseMapper<User> { } 

測試批量插入

完成上面這些工作后,就可以使用 Mybatis Plus 提供的批量插入功能了。我們新建一個單元測試,并注入?UserMapper?:

@Autowired
private UserMapper userMapper;

單元測試如下:

@Test
void testInsertBatch() {
    List<User> users = new ArrayList<>(); for (int i = 0; i < 3; i++) { User user = new User(); user.setName("犬小哈" + i); user.setAge(i); user.setGender(1); users.add(user); } userMapper.insertBatchSomeColumn(users); } 

控制臺實際執(zhí)行 SQL 如下:

mybatisplus批量新增數(shù)據(jù),mybatis,spring boot,mysql,java,數(shù)據(jù)庫

可以看到這次是真實的批量插入了,舒服了~

性能對比

我們來測試一下插入 105000 條數(shù)據(jù),分別使用?for?循環(huán)插入數(shù)據(jù)、savaBatch()?偽批量插入、與真實批量插入三種模式,看看耗時差距多少。

小哈這里的機器配置如下:

mybatisplus批量新增數(shù)據(jù),mybatis,spring boot,mysql,java,數(shù)據(jù)庫

for?循環(huán)插入

單元測試代碼如下:

@Test
void testInsert1() {
    // 總耗時:722963 ms, 約 12 分鐘 long start = System.currentTimeMillis(); for (int i = 0; i < 105000; i++) { User user = new User(); user.setName("犬小哈" + i); user.setAge(i); user.setGender(1); userMapper.insert(user); } System.out.println(String.format("總耗時:%s ms", System.currentTimeMillis() - start)); } 

savaBatch()?偽批量插入

單元測試代碼如下:

@Test
void testInsert2() {
    // 總耗時:95864 ms, 約一分鐘30秒左右 long start = System.currentTimeMillis(); List<User> users = new ArrayList<>(); for (int i = 0; i < 105000; i++) { User user = new User(); user.setName("犬小哈" + i); user.setAge(i); user.setGender(1); users.add(user); } userService.saveBatch(users); System.out.println(String.format("總耗時:%s ms", System.currentTimeMillis() - start)); } 

真實批量插入

注意,真實業(yè)務(wù)場景下,也不可能會將 10 萬多條記錄組裝成一條 SQL 進行批量插入,因為數(shù)據(jù)庫對執(zhí)行 SQL 大小是有限制的(這個數(shù)值可以自行設(shè)置),還是需要分片插入,比如取 1000 條執(zhí)行一次批量插入,單元測試代碼如下:

@Test
    void testInsertBatch1() {
        // 總耗時:6320 ms, 約 6 秒 long start = System.currentTimeMillis(); List<User> users = new ArrayList<>(); for (int i = 0; i < 1006; i++) { User user = new User(); user.setName("犬小哈" + i); user.setAge(i); user.setGender(1); users.add(user); } // 分片插入(每 1000 條執(zhí)行一次批量插入) int batchSize = 1000; int total = users.size(); // 需要執(zhí)行的次數(shù) int insertTimes = total / batchSize; // 最后一次執(zhí)行需要提交的記錄數(shù)(防止可能不足 1000 條) int lastSize = batchSize; if (total % batchSize != 0) { insertTimes++; lastSize = total%batchSize; } for (int j = 0; j < insertTimes; j++) { if (insertTimes == j+1) { batchSize = lastSize; } // 分片執(zhí)行批量插入 userMapper.insertBatchSomeColumn(users.subList(j*batchSize, (j*batchSize+batchSize))); } System.out.println(String.format("總耗時:%s ms", System.currentTimeMillis() - start)); } 

耗時對比

方式 總耗時
for?循環(huán)插入 722963 ms, 約 12 分鐘
savaBatch()?偽批量插入 95864 ms, 約一分鐘30秒左右
真實批量插入 6320 ms, 約 6 秒

耗時對比非常直觀,在大批量數(shù)據(jù)新增的場景下,批量插入性能最高。

結(jié)語

本小節(jié)中,我們學(xué)習(xí)了如何通過 Mybatis Plus 的 SQL 注入器實現(xiàn)真實的批量插入,同時最后還對比了三種不同方式插入 10 萬多數(shù)據(jù)的耗時,很直觀的看到在海量數(shù)據(jù)場景下,批量插入的性能是最強的。文章來源地址http://www.zghlxwxcb.cn/news/detail-767676.html

到了這里,關(guān)于spring boot集成mybatis-plus——Mybatis Plus 批量 Insert_新增數(shù)據(jù)(圖文講解)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Spring Boot學(xué)習(xí)隨筆- 集成MyBatis-Plus(二)條件查詢QueryWrapper、聚合函數(shù)的使用、Lambda條件查詢

    Spring Boot學(xué)習(xí)隨筆- 集成MyBatis-Plus(二)條件查詢QueryWrapper、聚合函數(shù)的使用、Lambda條件查詢

    學(xué)習(xí)視頻:【編程不良人】Mybatis-Plus整合SpringBoot實戰(zhàn)教程,提高的你開發(fā)效率,后端人員必備! 普通查詢 條件構(gòu)造器查詢 【重要】 AbstractWrapper ?是 MyBatis Plus 中的一個抽象類,用于構(gòu)建 SQL 查詢條件。定義了泛型? T 、 C ?和? Children 。其中, T ?表示實體類的類型, C ?表示查

    2024年02月04日
    瀏覽(24)
  • Spring Boot學(xué)習(xí)隨筆- 集成MyBatis-Plus,第一個MP程序(環(huán)境搭建、@TableName、@TableId、@TableField示例)

    Spring Boot學(xué)習(xí)隨筆- 集成MyBatis-Plus,第一個MP程序(環(huán)境搭建、@TableName、@TableId、@TableField示例)

    學(xué)習(xí)視頻:【編程不良人】Mybatis-Plus整合SpringBoot實戰(zhàn)教程,提高的你開發(fā)效率,后端人員必備! MyBatis-Plus是一個基于MyBatis的增強工具,旨在簡化開發(fā),提高效率。它擴展了MyBatis的功能,提供了許多實用的特性,包括強大的CRUD操作、條件構(gòu)造器、分頁插件、代碼生成器等。MyBa

    2024年02月04日
    瀏覽(24)
  • Spring Boot學(xué)習(xí)隨筆- 集成MyBatis-Plus(一),第一個MP程序(環(huán)境搭建、@TableName、@TableId、@TableField示例)

    Spring Boot學(xué)習(xí)隨筆- 集成MyBatis-Plus(一),第一個MP程序(環(huán)境搭建、@TableName、@TableId、@TableField示例)

    學(xué)習(xí)視頻:【編程不良人】Mybatis-Plus整合SpringBoot實戰(zhàn)教程,提高的你開發(fā)效率,后端人員必備! MyBatis-Plus是一個基于MyBatis的增強工具,旨在簡化開發(fā),提高效率。它擴展了MyBatis的功能,提供了許多實用的特性,包括強大的CRUD操作、條件構(gòu)造器、分頁插件、代碼生成器等。MyBa

    2024年02月04日
    瀏覽(17)
  • Spring Boot學(xué)習(xí)隨筆- 集成MyBatis-Plus(三)自定義SQL、分頁實現(xiàn)(PaginationInterceptor )、更新和刪除詳細方法

    學(xué)習(xí)視頻:【編程不良人】Mybatis-Plus整合SpringBoot實戰(zhàn)教程,提高的你開發(fā)效率,后端人員必備! 自定義mapper文件是為了應(yīng)對一些更復(fù)雜的查詢場景,首先先配置映射路徑 由于這里的mapper文件放在java文件夾中,所以要在pom.xml里進行配置 mapper 測試 在MyBatis Plus中, 物理分頁 和 內(nèi)

    2024年02月03日
    瀏覽(26)
  • Spring Boot整合MyBatis-Plus

    Spring Boot整合MyBatis-Plus

    引言 在現(xiàn)代軟件開發(fā)中,我們經(jīng)常需要處理大量的數(shù)據(jù)。為了有效地管理這些數(shù)據(jù),我們需要使用一些強大的框架。其中,Spring Boot和MyBatis-Plus是兩個非常流行的框架。Spring Boot是一個基于Spring的開源Java框架,可以用于創(chuàng)建獨立的、生產(chǎn)級別的Spring應(yīng)用。MyBatis-Plus是一個MyB

    2024年01月19日
    瀏覽(32)
  • Spring Boot 整合MyBatis-Plus

    Spring Boot 整合MyBatis-Plus

    ??前言 本篇博文是關(guān)于Spring Boot 整合MyBatis-Plus的,希望你能夠喜歡?? ??個人主頁:晨犀主頁 ??個人簡介:大家好,我是晨犀,希望我的文章可以幫助到大家,您的滿意是我的動力???? ??歡迎大家:這里是CSDN,我總結(jié)知識的地方,歡迎來到我的博客,感謝大家的觀看??

    2024年02月11日
    瀏覽(32)
  • spring boot mybatis-plus操作實踐

    1、先建一個數(shù)據(jù)表實體類 2、service目錄下新建接口IDeptService,然后擴展mp的IService 3、service目錄的impl目錄下新建類 DeptServiceImpl,擴展mp的ServiceImpl,實現(xiàn)接口IDeptService,然后注冊@Service 注解 4、DeptMapper 接口需要擴展mp的BaseMapper接口 5、調(diào)試一下看看是否可以使用

    2024年02月01日
    瀏覽(24)
  • spring boot3整合mybatis-plus

    spring boot3整合mybatis-plus

    添加依賴 配置屬性信息 編寫業(yè)務(wù)邏輯測試代碼 配置mybatis-plus分頁插件 配置mybatis-plus之屬性自動填充 如圖所示 1、添加依賴 2、配置屬性 3、編寫測試代碼 4、XML文件 5、測試數(shù)據(jù)是否能走通

    2024年03月12日
    瀏覽(24)
  • spring boot+mybatis-plus配置讀寫分離

    對于mysql主從機制的讀寫分離,對于寫操作寫入主庫,讀取操作讀取從庫 一、安裝依賴 二、配置文件配置數(shù)據(jù)源 三、在service,如果是讀取操作的話,則需要加上注解@DS(“slave”)即可,可看如下示例

    2024年01月25日
    瀏覽(22)
  • Spring Boot + MyBatis-Plus實現(xiàn)數(shù)據(jù)庫讀寫分離

    Spring Boot + MyBatis-Plus實現(xiàn)數(shù)據(jù)庫讀寫分離

    ??Spring Boot + MyBatis-Plus實現(xiàn)數(shù)據(jù)庫讀寫分離 ☆* o(≧▽≦)o *☆嗨~我是IT·陳寒?? ?博客主頁:IT·陳寒的博客 ??該系列文章專欄:架構(gòu)設(shè)計 ??其他專欄:Java學(xué)習(xí)路線 Java面試技巧 Java實戰(zhàn)項目 AIGC人工智能 數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí) ??文章作者技術(shù)和水平有限,如果文中出現(xiàn)錯誤,希望

    2024年02月05日
    瀏覽(44)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包