mybatis-plus的基础入门(二)之分页查询

 mybatis-plus3.4.0版本之前

 pom.xml文件

   <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>

    <!--分页插件-->

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.11</version>
        </dependency>

3.4.0版本之后

pom.xml文件

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3.1</version>
        </dependency>

   我是用的是3.4.3.1版本的依赖,倘若你想使用其他版本的依赖,你也可以自行去Maven仓库查找。

仓库地址:https://mvnrepository.com/artifact/com.baomidou/mybatis-plus

3.4.0之前的配置文件


import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * mybatis-plus配置
 * @author zyy
 * @date 2021/1/18 11:51
*/
@Configuration
public class MyBatisConfig {

    /**
     * mybatis-plus分页插件<br>
     * 文档:http://mp.baomidou.com<br>
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
     // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
     // paginationInterceptor.setOverflow(false);
     // 设置最大单页限制数量,默认 500 条,-1 不受限制
     // paginationInterceptor.setLimit(500);
     // 开启 count 的 join 优化,只针对部分 left join
     // paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }

}

3.4.0之后的配置文件

 分页插件


import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
@MapperScan("com.classfee.chen.Mapper")
public class MybatisPlusConfig {
 
    /**
     *
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

    我们要将mybatisPlusInterceptor 这个方法注册到Bean里面,不然我们的插件就会失效。
        使用@MapperScan这个注解,让系统扫描我们的Mapper类。注意一定要指定正确的Mapper地址。
        在类方法上上面使用注解:@Configuration表面这是一个config类。
         到这里我们的分页插件也就导入完成了,然后我们就需要去应用了。

语法总结

方法名说明用法实例等价SQL
allEq(Map<R, V> params)全部等于map.put(“id”,“3”);map.put(“user_name”,“IT可乐”);allEq(map)user_name = “IT可乐” AND id = 3
eq(R column, Object val)等于 =eq(“id”,“3”)id = 3
ne(R column, Object val)不等于 <>ne(“id”, “3”)id <> 3
gt(R column, Object val)大于 >gt(“user_age”,“18”)user_age > 18user_age > 18
ge(R column, Object val)大于等于 >=ge(“user_age”,“18”)user_age >= 18
lt(R column, Object val)小于 <lt(“user_age”,“18”)user_age < 18
le(R column, Object val)小于等于 <=le(“user_age”,“18”)user_age <= 18
between(R column, Object val1, Object val2)BETWEEN 值1 AND 值2between(“user_age”,“18”,“25”)user_age BETWEEN 18 AND 25
notBetween(R column, Object val1, Object val2)NOT BETWEEN 值1 AND 值2notBetween(“user_age”,“18”,“25”)user_age NOT BETWEEN 18 AND 25
like(R column, Object val)LIKE ‘%值%’like(“user_name”,“可乐”)like ‘%可乐%’
notLike(R column, Object val)NOT LIKE ‘%值%’notLike(“user_name”,“可乐”)not like ‘%可乐%’
likeLeft(R column, Object val)LIKE ‘%值’likeLeft(“user_name”,“可乐”)like ‘%可乐’
likeRight(R column, Object val)LIKE ‘值%’likeRight(“user_name”,“可乐”)like ‘可乐%’
isNull(R column)字段 IS NULLisNull(“user_name”)user_name IS NULL
isNotNull(R column)字段 IS NOT NULLisNotNull(“user_name”)user_name IS NOT NULL
in(R column, Collection<?> value)字段 IN (value.get(0), value.get(1), …)in(“user_age”,{1,2,3})user_age IN (?,?,?)
notIn(R column, Collection<?> value)字段 NOT IN (value.get(0), value.get(1), …)notIn(“user_age”,{1,2,3})user_age NOT IN (?,?,?)
inSql(R column, String inValue)字段 IN ( sql语句 )inSql(“id”,“select id from user”)id IN (select id from user)
notInSql(R column, String inValue)字段 NOT IN ( sql语句 )notInSql(“id”,“select id from user where id > 2”)id NOT IN (select id from user where id > 2
groupBy(R… columns)分组:GROUP BY 字段, …groupBy(“id”,“user_age”)GROUP BY id,user_age
orderByAsc(R… columns)排序【升序】:ORDER BY 字段, … ASCorderByAsc(“id”,“user_age”)ORDER BY id ASC,user_age ASC
orderByDesc(R… columns)排序【降序】:ORDER BY 字段, … DESCorderByDesc(“id”,“user_age”)ORDER BY id DESC,user_age DESC
orderBy(boolean condition, boolean isAsc, R… columns)ORDER BY 字段, …orderBy(true,true,“id”,“user_age”)ORDER BY id ASC,user_age ASC
having(String sqlHaving, Object… params)HAVING ( sql语句 )having(“sum(user_age)>{0}”,“25”)HAVING sum(user_age)>25
or()拼接 OReq(“id”,1).or().eq(“user_age”,25)id = 1 OR user_age = 25
and(Consumerconsumer)AND 嵌套and(i->i.eq(“id”,1).ne(“user_age”,18))id = 1 AND user_age <> 25
nested(Consumerconsumer)正常嵌套 不带 AND 或者 ORnested(i->i.eq(“id”,1).ne(“user_age”,18))id = 1 AND user_age <> 25
apply(String applySql, Object… params)拼接 sql(不会有SQL注入风险)apply(“user_age>{0}”,“25 or 1=1”)user_age >‘25 or 1=1’
last(String lastSql)拼接到 sql 的最后,多次调用以最后一次为准(有sql注入的风险)last(“limit 1”)limit 1
exists(String existsSql)拼接 EXISTS ( sql语句 )exists(“select id from user where user_age = 1”)EXISTS (select id from user where user_age = 1)

通用文件

 yml配置文件

# PageHelper 分页插件配置
pagehelper:
  helper-dialect: mysql
  reasonable: true
  supportMethodsArguments: true
  params: count=countSql
  page-size-zero: true

mybatis:
  # config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true	# 也可以在 yml 配置文件中设置属性
    # 开启日志功能
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  type-aliases-package: com.lss.domain

        helper-dialect:指定数据库,不指定的话会默认自动检测数据库类型
        reasonable:是否启动分页合理化。如果启用,当 pagenum < 1 时,会自动查询第一页的数据,当 pagenum > pges 时,自动查询最后一页数据;不启用的,以上两种情况都会返回空数据,如果启用则 pageHelper可以自动拦截请求参数中的 pageNum,pageSize参数,否则需要使用 PageHelper.startPage(pageNum,pageSize) 方法调用。
        support-methods-arguments:默认为 false,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。
        params:用于从对象中根据属性名取值,可以配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值,默认值为 pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero

 条件构造器

在这里插入图片描述

QueryWrapper查询
QueryWrapper<实体类> queryWrapper = new QueryWrapper<>();
List<Long> ids= new ArrayList<>();
queryWrapper.in("id",ids); // 可入参数组查询
queryWrapper.and(wrapper->wrapper.eq("数字库字段",入参数据));   //可进行嵌套子查询

时间段查询

// 查询开始时间
String startTime = "2022-04-19"; //yyyy-MM-dd HH:mm:ss
queryWrapper.apply("UNIX_TIMESTAMP(start_time)>=UNIX_TIMESTAMP('" + startTime + "')");
//queryWrapper.ge("start_time",startTime);

// 结束时间
String endTime = "2022-04-20"; //yyyy-MM-dd HH:mm:ss
queryWrapper.apply("UNIX_TIMESTAMP(end_time)<=UNIX_TIMESTAMP('" + endTime + "')");
//queryWrapper.le("end_time",endTime);

// 备注:存入数据库的时间格式,和查询时间格式必须统一

condition(动态组装查询条件)

查询名字中包含n,年龄大于10且小于20的用户,查询条件来源于用户输入,是可选的

/**
*  使用if语句动态判断
*/
@Test
public void test1() {
    
    //定义查询条件,有可能为null(用户未输入)
    String name = null;
    Integer ageBegin = 10;
    Integer ageEnd = 20;

    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    if(StringUtils.isNotBlank(name)){
        queryWrapper.like("name","n");
    }
    if(ageBegin != null){
        queryWrapper.ge("age", ageBegin);
    }
    if(ageEnd != null){
        queryWrapper.le("age", ageEnd);
    }

    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}

使用带condition参数的重载方法构建查询条件,简化代码的编写

@Test
public void test1Condition() {

    //定义查询条件,有可能为null(用户未输入)
    String name = null;
    Integer ageBegin = 10;
    Integer ageEnd = 20;

    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper
        .like(StringUtils.isNotBlank(name), "name", "n")
        .ge(ageBegin != null, "age", ageBegin)
        .le(ageEnd != null, "age", ageEnd);

    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}

LambdaQueryWrapper

@Test
public void test2() {

    //定义查询条件,有可能为null(用户未输入)
    String name = null;
    Integer ageBegin = 10;
    Integer ageEnd = 20;

    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper
        //避免使用字符串表示字段,防止运行时错误
        //User 是用户实体类
        .like(StringUtils.isNotBlank(name), User::getName, "n")
        .ge(ageBegin != null, User::getAge, ageBegin)
        .le(ageEnd != null, User::getAge, ageEnd);

    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}

第一种实现的方法

 controller层

    //分页
     @PostMapping("page")
    public R page(@RequestBody(required = false) UserVo userVo){
        //当前页
    	//int page = query.getCurrent() == null ? 1 : query.getCurrent();
		//每页的页数
        //int pageSize = query.getSize() == null ? 10 : query.getSize();
        //创建一个分页对象  一般post 都是使用一个类文件接受相对应的参数
        Page<User> objectPage = new Page<>(userVo.getPage(),userVo.getSize());
        //构造查询条件
        QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
        //条件查询
        //名称
        String name = userVo.getUserName();
        //开始名称
        String startTime = userVo.getStartTime();
        //结束名称        
        String endTime = userVo.getEndTime();
        //部门
        String deptName =userVo.getDeptName();
        //判断是否为空不为空则拼接
        if (!StringUtils.isEmpty(deptName )){
            //根据部门名查询部门名称
            Dept one = deptService.findOneByName(deptName);
            //实体类不为空则把部门id传进去为空传null            
            if (one!=null){
                //前面数据库字段后面传递的参数
                objectQueryWrapper.eq("dept_id", one.getId());
            }else {
                objectQueryWrapper.eq("dept_id", null);
            }
        }


        if (!StringUtils.isEmpty(name)){
                objectQueryWrapper.eq("real_name", name);
           
        }


    
        if(!StringUtils.isEmpty(startTime)){
                   objectQueryWrapper.apply("UNIX_TIMESTAMP(time)>=UNIX_TIMESTAMP('" + startTime + "')");
        }
   
        if(!StringUtils.isEmpty(endTime)){
                      objectQueryWrapper.apply("UNIX_TIMESTAMP(time)<=UNIX_TIMESTAMP('" + endTime + "')");
        }

        //调用方法 使用分页
        Page<TGridPunchRecordEntity> page = UserService.page(objectPage, objectQueryWrapper);
        page.getRecords().forEach(tGridPunchRecordEntity -> {
               tGridPunchRecordEntity.setName(tsUserService.findById(tGridPunchRecordEntity.getUserId()).getRealName());
                }
        );

        long total = objectPage.getTotal();  //总记录数

      //  List<TGridPunchRecordEntity> records = objectPage.getRecords(); //集合

        List<TGridPunchRecordEntity> records = page.getRecords();

        return R.okPage(records,total);
    }

service需要继承IService<实体类>

public interface UserService  extends IService<UserEntity> {



}

第二种实现的方法

    /**
     * 使用PageHelper进行分页操作 并对parms中的Key进行模糊查询
     */
    @GetMapping("/findPage")
    public R findPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize,
                             @RequestParam Map<String, Object> params) {

        PageInfo pageInfo = deptService.pageHelper(pageNum,pageSize,params);
        return R.ok(pageInfo);
    }

    /**
     * 使用Mybatis-plus自带分页操作 并对parms中的Key进行模糊查询
     */
    @GetMapping("/findPageByMybatisPlus")
    public R findPageByMybatisPlus(@RequestParam Integer pageNum, @RequestParam Integer pageSize,
                                       @RequestParam Map<String, Object> params) {


        IPage page = deptService.pageByMybatisPlus(pageNum,pageSize,params);
        return R.ok(page);
    }

Service层

PageInfo pageHelper(Integer pageNum, Integer pageSize, Map<String, Object> params);

IPage pageByMybatisPlus(Integer pageNum, Integer pageSize, Map<String, Object> params);

serviceImpl

 @Override
    public PageInfo pageHelper(Integer pageNum, Integer pageSize, Map<String, Object> params) {
        //首先创建一个queryWrapper
        QueryWrapper<DeptEntity> queryWrapper = new QueryWrapper<>();
        //开启分页功能
        PageHelper.startPage(pageNum,pageSize);

        // 如果有传来的params中有Key这个数据 我们让其对Name进行模糊查询
        String key = (String) params.get("key");
        if (StringUtils.hasText(key)){
            queryWrapper.like("name",key);
        }

        //查所有数据返回
        PageInfo pageInfo = new PageInfo(deptDao.selectList(queryWrapper));
        return pageInfo;
    }

    @Override
    public IPage pageByMybatisPlus(Integer pageNum, Integer pageSize, Map<String, Object> params) {
        QueryWrapper<DeptEntity> queryWrapper = new QueryWrapper<>();
        String key = (String) params.get("key");
        //如果名字等于Key 或者 email like key再查询出结果
        if (StringUtils.hasText(key)){
            queryWrapper.eq("name",key).or().like("email",key);
        }
        IPage<DeptEntity> page = this.page(new Page<>(pageNum, pageSize), queryWrapper);
        return page;

    }

结果测试

http://localhost:8082/page/1?pageNum=1&pageSize=5&key=孙
在这里插入图片描述

第三种实现方法

Controller层

   @GetMapping("query/{current}/{limit}")
    public List<DeptEntity> query(@PathVariable Long current, @PathVariable Long limit,
                                  DeptVo deptVo){
        //current为当前页,limit为每页显示个数,voQuery为封装的查询条件
        List<DeptEntity> pagequery = deptService.Pagequery(current,limit,deptVo);
        return pagequery;
    }

Service

    List<DeptEntity> Pagequery(Long current, Long limit, DeptVo deptVo);

ServiceImpl

    @Override
    public List<DeptEntity> Pagequery(Long current, Long limit, DeptVo deptVo) {
        //初始化page
        Page<DeptEntity> page = new Page<>(current,limit);

        //设置条件
        QueryWrapper<DeptEntity> wrapper =new QueryWrapper<>();
        //eq是等于,ge是大于等于,gt是大于,le是小于等于,lt是小于,like是模糊查询

        if(!StringUtils.isEmpty(deptVo.getName())){
            wrapper.like("name",deptVo.getName());
        }
    

        //执行查询
        deptService.page(page,wrapper);


        long total = page.getTotal();//总数
        List<DeptEntity> rs = page.getRecords();//结果
        return rs;
    }

第四种方法

 Controller层

@GetMapping("/list")
@ApiOperation(value = "按条件分页查询")
public R list(@ApiParam(value = "当前页码", required = true) Long current,
       @ApiParam(value = "每页记录数", required = true) Long size,
       @ApiParam("查询对象条件") XXXVO xxxVO) {

    //分页参数
    Page<KnowledgeData> page = new Page<>(current, size);
    //调用service层查询
    IPage<实体类> pageMode = knowledgeDataService.selectPage(page, xxxVO);
    //分页查询 获取返回数据
    List<实体类> dataList = pageMode.getRecords();
    //获取查询数据总记录数
    long total = pageMode.getTotal();

    HashMap<Object, Object> map = new HashMap<>();
    map.put("total", total);
    map.put("data", dataList);

    return R.data(map);
}

service层

public IPage<实体类> selectPage(Page<实体类> page, XXXVO xxxVO) {
    QueryWrapper<实体类> queryWrapper = new QueryWrapper<>();
    //中间判断 加查询条件
    Page<实体类> selectPage = baseMapper.selectPage(page, queryWrapper);
    return selectPage;
}

自定义的 mapper#method 使用分页
UserMapper.java中定义接口方法

    /**
     * 查询 : 根据年龄查询用户列表,分页显示
     *
     * @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位
     * @param age 年龄
     * @return 分页对象
     */
    IPage<User> selectPageByPage(Page<?> page, Integer age);

自定义UserMapper.java.xml

<select id="selectPageByPage" resultType="com.lyh.mybatisplus.entity.User">
    SELECT id,name FROM user WHERE age > #{age}
</select>

乐观锁

在实体类的字段上加上@Version注解

@Version
private Integer version;

说明

**例子:**假设两个同时执行数据更新操作,会造成只有一个执行成功,另一个会被覆盖。
说明:

支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
整数类型下 newVersion = oldVersion + 1
newVersion 会回写到 entity 中
仅支持 updateById(id) 与 update(entity, wrapper) 方法
在 update(entity, wrapper) 方法下, wrapper 不能复用!!!

常用注解

@TableName
@TableName(value = "t_user") //对应数据库中表的名字
public class User {
    @TableId
    @TableId(value = "uid") //映射数据表中的列名
    private String id;
    @TableField(可配置自动填充时间)
    @TableField(value = "name") //映射数据表中的列名
    private String name;

    //自动填充表数据:创建时间、更新时间

    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
}    

// 注意:当对象的id被明确赋值时,不会使用雪花算法
@TableId(type = IdType.ASSIGN_ID) //雪花算法策略生成数据id
private Long id;

@TableId(type = IdType.AUTO) //使用数据库的自增策略
private Long id;
 

自动填充时间的处理类MyMetaObjectHandler.java
实现元对象处理器接口 -> 创建handler包,创建MyMetaObjectHandler类

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
        this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
    }
}

@TableLogic逻辑删除

物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据
逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
使用场景:可以进行数据恢复
数据库中创建逻辑删除状态列

实体类中添加逻辑删除属性

@TableLogic
@TableField(value = "is_deleted")
private Integer deleted;

mybatis-plus时间范围查询的3种方式

实体类字段设置

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("开始时间")
@TableField(exist = false)
private Date startTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("截止时间")
@TableField(exist = false)
private Date endTime;

或者

@ApiModelProperty("开始时间")
@TableField(exist = false)
private Date startTime;
@ApiModelProperty("截止时间")
@TableField(exist = false)
private Date endTime;

数据库的create_time字段类型为datetime
第一种:
使用框架提供的查询方法

QueryWrapper<Goods> queryWrapper = Condition.getQueryWrapper(goods)
        .ge(Func.isNotEmpty(goods.getStartTime()),"create_time",goods.getStartTime())
            .le(Func.isNotEmpty(goods.getEndTime()),"create_time",goods.getEndTime());
IPage<Goods> pages = goodsService.page(Condition.getPage(query), queryWrapper);

第二种:
适用于自定义的查询方法

<if test="order.startTime != null">
    and o.create_time &gt;= #{order.startTime}
</if>
<if test="order.endTime != null">
    and o.create_time &lt;= #{order.endTime}
</if>

第三种:
lambda方法构造查询方法

QueryWrapper<Goods> queryWrapper = new QueryWrapper<>();
LambdaQueryWrapper<Goods> lambdaQueryWrapper = queryWrapper.lambda().ge(Func.isNotEmpty(goods.getStartTime()),Goods::getCreateTime, goods.getStartTime());
ambdaQueryWrapper = lambdaQueryWrapper.le(Func.isNotEmpty(goods.getEndTime()),Goods::getCreateTime, goods.getEndTime());
IPage<Goods> pages = goodsService.page(Condition.getPage(query), lambdaQueryWrapper);

打印日志:

第一种

mybatis-plus:
  configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志
 
或者:
 
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl #关闭sql日志

第二种

logging:
  level:
    com.app.mapper: debug

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值