Mybatis-plus是使用,告别繁琐的CRUD编写,自动生成直接使用

目录

一、简介

1. 是什么

2. 特性

3. 框架结构

4. 常用注解

二、搭建使用

1. 依赖

2. 生成器

3. 生成

4. 引用

5. 路径访问

三、测试

四、雪花ID

每篇一获


Mybatis-plus(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

一、简介

Mybatis-plus官方文档icon-default.png?t=N7T8https://baomidou.com/pages/24112f/

1. 是什么

Mybatis-plus是一个基于Mybatis的增强工具,它在Mybatis的基础上进行了扩展,提供了更加便捷、高效的数据库操作方式。Mybatis-plus通过封装Mybatis的API,简化了开发人员对数据库的操作,提高了开发效率。

Mybatis-plus提供了一些特性和功能,包括自动生成SQL、性能优化、多种查询方式、代码生成器、分页插件、逻辑删除等。通过这些功能,开发人员不需要编写繁琐的SQL语句,可以通过简单的编码实现对数据库的操作。例如,使用Mybatis-plus可以通过简单的注解和方法调用实现增删改查操作,大大简化了开发流程。

此外,Mybatis-plus还提供了代码生成器,可以根据数据库表自动生成实体类、Mapper接口和XML文件,减少了手动编写重复代码的工作量,提高了开发效率。同时,Mybatis-plus还提供了分页插件,可以方便地实现分页查询功能,减少了对分页逻辑的重复编写。

总之,Mybatis-plus是一个强大的增强工具,它简化了Mybatis的使用方式,提高了开发效率,使开发人员能够更加专注于业务逻辑的实现。因此,Mybatis-plus在Java项目中被广泛应用,成为了Mybatis的重要补充和扩展。

支持的数据库 

任何能使用 MyBatis 进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下,如果不在下列表查看分页部分教程 PR 您的支持。

  • MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb,informix,TDengine,redshift

  • 达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库,优炫数据库,星瑞格数据库

2. 特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

3. 框架结构

框架结构图

Mybatis-plus的框架结构主要包括以下几个核心部分:

1. Entity:实体类,用于映射数据库表的字段和Java对象的属性。在Mybatis-plus中,可以通过注解或配置文件来定义实体类,并与数据库表进行映射。

2. Mapper:Mapper接口,用于定义数据库操作的方法。在Mybatis-plus中,Mapper接口可以通过继承Mybatis-plus提供的BaseMapper接口来获得通用的增删改查方法,也可以自定义SQL方法来实现特定的数据库操作。

3. Service:Service层,用于封装业务逻辑。在Mybatis-plus中,Service层通常与Mapper层配合使用,通过调用Mapper接口中的方法来实现业务逻辑。

4. Controller:Controller层,用于处理用户请求和返回响应。在Mybatis-plus中,Controller层通常与Service层配合使用,通过调用Service层的方法来处理业务逻辑,并返回相应的结果给用户。

5. SQL解析器:Mybatis-plus内置了SQL解析器,可以根据方法名自动生成SQL,简化了SQL的编写。

6. 分页插件:Mybatis-plus提供了分页插件,可以方便地实现分页查询功能。

总的来说,Mybatis-plus的框架结构与传统的Mybatis框架类似,但在Mapper接口的定义、SQL解析和分页插件等方面进行了增强和优化,使得开发人员能够更加便捷地进行数据库操作和业务逻辑的实现。

4. 常用注解

本文将介绍 MybatisPlus 注解包相关类详解(更多详细描述可点击查看源码注释)

  • 1. @TableName:指定实体对应的数据库表名。
  • 2. @TableId:标识实体的主键字段。
  • 3. IdType:指定主键生成策略。
  • 4. @TableField:标识实体对应的数据库字段名。
  • 5. FieldStrategy:指定字段的策略(例如,自动填充、逻辑删除等)。
  • 6. FieldFill:指定字段填充策略。
  • 7. @Version:用于乐观锁机制,标识乐观锁字段。
  • 8. @EnumValue:指定枚举类字段对应的数据库存储值。
  • 9. @TableLogic:指定逻辑删除字段。
  • 10. @SqlParser:指定 SQL 解析规则。
  • 11. @KeySequence:指定序列的名称。
  • 12. @InterceptorIgnore:忽略拦截器。
  • 13. @OrderBy:指定查询结果的排序方式。

更加详细的可以观看官方文档中 : MybatisPlus注解文档icon-default.png?t=N7T8https://baomidou.com/pages/223848/#tablename

二、搭建使用

1. 依赖

我们创建一个spring-boot项目。

在pom.xml文件中引用以下依赖 : 

        <!-- mybatis-plus依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!-- mybatis-plus 代码生成器的依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--MYSQL 依赖-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--模板引擎freemarker依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!-- 雪花ID的依赖-->
        <dependency>
            <groupId>com.github.yitter</groupId>
            <artifactId>yitter-idgenerator</artifactId>
            <version>1.0.6</version>
        </dependency>

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>
    <groupId>com.Jun.depend</groupId>
    <artifactId>demo01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo01</name>
    <description>demo01</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.6.13</spring-boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </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-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
       <!-- mybatis-plus依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!-- mybatis-plus 代码生成器的依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--MYSQL 依赖-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--模板引擎freemarker依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!-- 雪花ID的依赖-->
        <dependency>
            <groupId>com.github.yitter</groupId>
            <artifactId>yitter-idgenerator</artifactId>
            <version>1.0.6</version>
        </dependency>

    </dependencies>
    <!--只负责定义依赖-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <mainClass>com.jun.demo01.Demo01Application</mainClass>
                    <skip>true</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

application.yml 配置文件的配置如下 : 

#server:
#    port: 8080
spring:
    datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/bookshop?useUnicode=true&characterEncoding=utf-8&useSSL=false
        username: root
        password: 123456
mybatis-plus:
    type-aliases-package:  com.jun.demo01.text #指定实体类路径
    configuration:
        map-underscore-to-camel-case: true #驼峰命名规范

2. 生成器

我这里根据管方的说生成器进行了改善,创建一个生成器。

MySQLGenerator :

package com.jun.demo01;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Slf4j
public class MySQLGenerator {

    private final static String URL = "jdbc:mysql://localhost:3306/bookshop";// 数据库连接URL
    private final static String USERNAME = "root";// 数据库用户名
    private final static String PASSWORD = "123456";// 数据库密码
    private final static DataSourceConfig.Builder DATA_SOURCE_CONFIG =
            new DataSourceConfig.Builder(URL, USERNAME, PASSWORD);

   public static void main(String[] args) {
        // 创建FastAutoGenerator对象,传入数据源配置
        FastAutoGenerator.create(DATA_SOURCE_CONFIG)
                // 全局配置,传入扫描器,构建器,并设置作者,输出目录,注释日期,日期类型
                .globalConfig(
                        (scanner, builder) ->
                                builder.author(scanner.apply("请输入作者名称?"))
                                        .outputDir(System.getProperty("user.dir") + "\\src\\main\\java")
                                        .commentDate("yyyy-MM-dd")
                                        .dateType(DateType.TIME_PACK)
                )
                // 包配置,传入构建器,并设置父包,实体,服务,服务实现,映射器,xml,xml路径信息
                .packageConfig((builder) ->
                        builder.parent("com.jun.demo01")
                                .entity("entity")
                                .service("service")
                                .serviceImpl("service.impl")
                                .mapper("mapper")
                                .xml("mapper.xml")
                                .pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "\\src\\main\\resources\\mapper"))
                )
                // 注入配置,传入构建器,并设置输出文件前执行的函数
                .injectionConfig((builder) ->
                        builder.beforeOutputFile(
                                (a, b) -> log.warn("tableInfo: " + a.getEntityName())
                        )
                )
               .strategyConfig((scanner, builder) ->
                        // 添加表名
                        builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
                                // 添加去除表前缀设置
                                .addTablePrefix("tb_", "t_", "lay_", "meeting_", "sys_")
                                // 实体配置
                                .entityBuilder()
                                // 启用链式模型
                                .enableChainModel()
                                // 启用 Lombok
                                .enableLombok()
                                // 启用表字段注解
                                .enableTableFieldAnnotation()
                                // 控制器配置
                                .controllerBuilder()
                                // 启用 REST 样式
                                .enableRestStyle()
                                // 启用连字符样式
                                .enableHyphenStyle()
                                // 构建
                                .build()
                )
                // 模板引擎
                .templateEngine(new FreemarkerTemplateEngine())
                // 执行
                .execute();
    }

    protected static List<String> getTables(String tables) {
        return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
    }

}

其中修改根据自己的数据源进行修改,还有软件包也需要跟自己的项目中的包结构一直。

3. 生成

根据如图,进行执行生成器 

执行的其中在控制器需要输入一个作者名称,可以根据自己的喜好输入,之后就是输入一个你连接数据库中的一个表名称,这个也就是你要生成代码的表。

生成完成后会弹出你生成这个表的代码的本地路径。

生成后的所有实体,服务,服务实现,映射器,xml,xml路径信息

4. 引用

生成完成之后,我们需要在生成后的Mappe类中,直接一个@Repository注解

如图 : 

之后就是需要在启动类中,增加@MapperScan注解,需要填写到mapper包

5. 路径访问

最后就是编写访问数据的路径,在控制器中编写代码 

BookController


 

package com.jun.demo01.controller;

import com.github.yitter.idgen.YitIdHelper;
import com.jun.demo01.entity.Book;
import com.jun.demo01.service.IBookService;
import kotlin.Metadata;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 书本信息表 前端控制器
 * @author cloudjun
 * @since 2023-12-16
 */
@RestController
@RequestMapping("/book")
public class BookController {

   @Autowired
    private IBookService iBookService;

    //获取列表
    @RequestMapping("/list")
    public Object list(){
       return  iBookService.list();
    }

    //保存
    @RequestMapping("/save")
    public Object save(Book book){
        //设置雪花ID需要将类型修改为Long类型
        book.setId(YitIdHelper.nextId());//YitIdHelper.nextId()获取雪花ID并且赋值到对象编号中
        return  iBookService.save(book);
    }

    //删除
    @RequestMapping("/del")
    public Object remove(Book book){
        return  iBookService.removeById(book);
    }

    //更新
    @RequestMapping("/update")
    public Object update(Book book){
        return  iBookService.updateById(book);
    }


}

三、测试

访问我们配置好的路径,进行数据的访问,对数据进行编辑

在演示一个增加,如图所示:

在查看数据表 : 

四、雪花ID

Snowflake官方文档icon-default.png?t=N7T8https://docs.snowflake.com/en/guides-overview

雪花ID(Snowflake ID)是一种分布式唯一ID生成算法,它的作用是生成全局唯一的ID,适用于分布式系统中对ID唯一性要求较高的场景。雪花ID的特点包括:

1. 分布式唯一性:雪花ID生成算法能够在分布式系统中生成全局唯一的ID,避免了不同节点生成ID的重复。

2. 有序性:雪花ID生成的ID是趋势递增的,即生成的ID在时间上是有序的,这样有利于数据库索引的性能优化。

3. 高性能:雪花ID生成算法是基于位运算和时间戳的快速算法,生成ID的效率较高。

4. 简单易用:雪花ID生成算法相对简单,实现起来比较容易,能够满足大部分分布式系统的ID生成需求。

雪花ID通常由64位的二进制组成,其中包括一个符号位、一个时间戳部分、一个机器ID部分、一个数据中心ID部分和一个序列号部分。这些部分的组合使得雪花ID具有全局唯一性和有序性。

总的来说,雪花ID的作用是在分布式系统中生成全局唯一的有序ID,它的特点包括分布式唯一性、有序性、高性能和简单易用,因此在分布式系统中被广泛应用于唯一ID的生成。

每篇一获

学习Mybatis-plus和Snowflake的使用可以带来以下收获:

1. 提高开发效率:Mybatis-plus提供了简化数据库操作的方法,使得开发人员能够更加专注于业务逻辑的实现,从而提高开发效率。而Snowflake可以快速生成全局唯一的ID,避免了手动编写ID生成算法的复杂性,也提高了开发效率。

2. 优化数据库性能:Mybatis-plus提供了SQL解析器和分页插件等功能,可以优化数据库查询的性能,提高系统的响应速度。同时,Snowflake生成的ID是有序的,有利于数据库索引的优化,进一步提高数据库的性能。

3. 实现分布式系统:Mybatis-plus和Snowflake都是分布式系统中常用的工具,学习它们的使用可以帮助开发人员更好地实现分布式系统,提高系统的可扩展性和可靠性。

4. 拓展技术视野:学习Mybatis-plus和Snowflake的使用可以拓展开发人员的技术视野,了解更多关于Java开发的技术和工具,提高自身的综合能力。

综上所述,学习Mybatis-plus和Snowflake的使用可以带来多方面的收获,对于Java开发人员来说是一项有益的技能。

  • 31
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Spring Boot整合MyBatis-Plus可以通过使用代码生成器自动生成CRUD代码。下面是使用步骤: 1. 首先,在pom.xml文件中添加MyBatis-Plus和相关依赖: ```xml <!-- MyBatis-Plus依赖 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>最新版本号</version> </dependency> <!-- MyBatis-Plus代码生成器依赖 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>最新版本号</version> </dependency> ``` 2. 创建一个配置类来配置代码生成器: ```java @Configuration public class MyBatisPlusConfig { @Value("${spring.datasource.url}") private String url; @Value("${spring.datasource.username}") private String username; @Value("${spring.datasource.password}") private String password; @Value("${spring.datasource.driver-class-name}") private String driverClassName; @Value("${mybatis-plus.package}") private String packageName; @Value("${mybatis-plus.author}") private String author; @Value("${mybatis-plus.table-prefix}") private String tablePrefix; @Bean public DataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); dataSource.setDriverClassName(driverClassName); return dataSource; } @Bean public GlobalConfig globalConfig() { GlobalConfig globalConfig = new GlobalConfig(); globalConfig.setAuthor(author); globalConfig.setOpen(false); return globalConfig; } @Bean public DataSourceConfig dataSourceConfig() { DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setDbType(DbType.MYSQL); dataSourceConfig.setDriverName(driverClassName); dataSourceConfig.setUsername(username); dataSourceConfig.setPassword(password); dataSourceConfig.setUrl(url); return dataSourceConfig; } @Bean public PackageConfig packageConfig() { PackageConfig packageConfig = new PackageConfig(); packageConfig.setParent(packageName); packageConfig.setEntity("entity"); packageConfig.setMapper("mapper"); packageConfig.setService("service"); packageConfig.setServiceImpl("service.impl"); packageConfig.setController("controller"); return packageConfig; } @Bean public StrategyConfig strategyConfig() { StrategyConfig strategyConfig = new StrategyConfig(); strategyConfig.setEntityColumnConstant(true); strategyConfig.setEntityLombokModel(true); strategyConfig.setNaming(NamingStrategy.underline_to_camel); strategyConfig.setInclude("表名1", "表名2"); // 生成指定的表 strategyConfig.setRestControllerStyle(true); strategyConfig.setTablePrefix(tablePrefix); // 设置表前缀 return strategyConfig; } @Bean public TemplateConfig templateConfig() { TemplateConfig templateConfig = new TemplateConfig(); templateConfig.setController(null); // 不生成controller层 return templateConfig; } @Bean public InjectionConfig injectionConfig() { Map<String, Object> map = new HashMap<>(); return new InjectionConfig() { @Override public void initMap() { this.setMap(map); } }; } @Bean public AutoGenerator autoGenerator() { AutoGenerator autoGenerator = new AutoGenerator(); autoGenerator.setGlobalConfig(globalConfig()); autoGenerator.setDataSource(dataSourceConfig()); autoGenerator.setPackageInfo(packageConfig()); autoGenerator.setStrategy(strategyConfig()); autoGenerator.setTemplate(templateConfig()); autoGenerator.setCfg(injectionConfig()); return autoGenerator; } } ``` 3. 在application.properties或application.yml文件中配置相关信息: ```properties # 数据源配置 spring.datasource.url=数据库URL spring.datasource.username=数据库用户名 spring.datasource.password=数据库密码 spring.datasource.driver-class-name=数据库驱动类名 # MyBatis-Plus配置 mybatis-plus.package=你的包路径 mybatis-plus.author=代码作者名 mybatis-plus.table-prefix=表前缀 ``` 4. 创建一个启动类,添加@SpringBootApplication和@EnableAutoConfiguration注解,并在main方法中调用代码生成器生成代码: ```java @SpringBootApplication @EnableAutoConfiguration public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); // 调用代码生成器生成代码 ApplicationContext context = SpringApplication.run(MyApplication.class, args); AutoGenerator autoGenerator = context.getBean(AutoGenerator.class); autoGenerator.execute(); } } ``` 5. 运行启动类,执行代码生成器。生成的代码将包含实体类、Mapper接口、Service接口、Service实现类和Controller类。 这样就能根据数据库表自动生成CRUD代码了。如果需要生成其他的代码,可以根据需要配置生成器相应的参数和模板。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值