MyBatis实现分页查询

11 篇文章 1 订阅
2 篇文章 0 订阅

目录

一、基于注解的简单分页查询

1.定义对象

 2.Mapper接口

3.Controller类

4.功能实现

二、基于注解的较复杂分页查询

1.定义shop实体类和page分页类

2.Mapper接口

3.Controller类

4.功能实现

三、基于mapper.xml的复杂分页查询

1.首先要配置一下xxxMapper.xml文件的地址:

1.定义Page类

2.Mapper接口

3.pageMapper.xml

4.pageService

5.pageService的实现类pageServiceImpl

6.功能实现

7.可扩展性测试

四、基于pagehelper插件的复杂分页查询

1. 导入依赖

2. 添加配置

3.OrderMapper与orderMapper.xml

 4. OrderService与OrderServiceImpl

5.OrderController

6.功能实现

7.Mybatis 分页插件 Pagehelper 的 PageInfo 字段属性解释

五、MybtisPlus插件自动分页配置

1、引入依赖

2、MybatisPlusConfig配置文件

3、项目中各层具体写法:


项目中经常遇到需要查询数据列表的功能,一般需要前端去调用后端的相应数据列表的分页接口,所以后端需要实现数据库SQL的分页查询:

一、基于注解的简单分页查询

1.定义对象

注意数据库要有相对应的数据库表

import ...

@Entity
@Data
@Table(name = "shop")
public class Shop {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @Column(name = "name")
    private String name;
}

 2.Mapper接口

import ...

@Repository
public interface ShopMapper {
    //分页查询
    @Select("select * from shop limit #{pageBegin}, #{pageSize}")
    List<Shop> findByPage(@Param("pageBegin") Integer pageBegin,@Param("pageSize") Integer pageSize);

3.Controller类

import ...

@RestController
@RequestMapping("shop")
public class ShopController {
    @Autowired
    private ShopMapper shopMapper;

    //分页查询
    @GetMapping("/allByPage")
    public List<Shop> findByPage(Integer page,Integer pageSize) {
        Integer pageBegin = (page-1) * pageSize;
        return shopMapper.findByPage(pageBegin,pageSize);
    }

4.功能实现

请求路径:http://localhost:8080/shop/allByPage?page=3&pageSize=5

请求结果:

[{"id":11,"name":"馒头店"},{"id":12,"name":"包子店"},{"id":13,"name":"豆腐脑油条"},{"id":14,"name":"北京烤鸭"},{"id":15,"name":"煎饼果子"}]

简单的分页查询功能已实现,但是功能需求多的话显然还不够用,比如要向前端展示一下共有多少页,有多少数据条,这些数据是从哪行到哪行等等,就实现不了了,因此对于分页的功能实现远远不止于此,下面就来进阶一下。

二、基于注解的较复杂分页查询

逻辑上跟简陋版是一样的,只不过多了一个Page类。这个类里面就包含了上边的Shop类,也就是之前返回的shop类的数组变成了Page类的一个属性值。

1.定义shop实体类和page分页类

Shop类用之前的就可以,下面是Page分页类:

import ...

@Data
public class ShopPage {
    //第几页
    private Integer pageNum;
    //每页数据条数
    private Integer pageSize;
    //总数据条数
    private Integer size;
    //起始(末尾)数据
    private Integer startRow;
    private Integer endRow;
    //总页数
    private Integer pages;
    //上(下)一页页码
    private Integer prePage;
    private Integer nextPage;
    //是否是第(最后)一行
    private Boolean isFirstPage;
    private Boolean isLastPage;
    //有无前(后)页
    private Boolean hasPreviousPage;
    private Boolean hasNextPage;
    private Integer navigatePages;
    private List navigatePageNums;
    //数据数组
    private List<Shop> data;
    private Integer navigateFirstPage;
    private Integer navigateLastPage;
    //第(最后)一页
    private Integer firstPage;
    private Integer lastPage;
}

这样就定义好了调用接口时所返回的数据类型,可以看到里面有一个List<Shop>,这就是我们查到的数据,和主要数据一起传给前端的还有各种各样的页码和条数数据,总之就是几乎将这些数据条的所有信息都传给前端。

2.Mapper接口

import ...

@Repository
public interface ShopPageMapper {


    @Select("select * from shop limit #{pageBegin}, #{pageSize}")
    List<Shop> findData(@Param("pageBegin") Integer pageBegin, @Param("pageSize") Integer pageSize);

    @Select("select count(*) from shop")
    int findSize();
}

这里先简单写一下,之后还得再修改。

3.Controller类

import ...

@RestController
@RequestMapping("page")
public class ShopPageController {

    @Autowired
    private ShopPageMapper shopPageMapper;

    @GetMapping("/shop")
    public ShopPage page(Integer page, Integer pageSize){
        ShopPage shopPage = new ShopPage();
        Integer pageBegin = (page-1) * pageSize;

        //当前页码
        shopPage.setPageNum(page);
        //前(后)一页页码
        shopPage.setPrePage(page - 1);
        shopPage.setNextPage(page + 1 );
        //总数据条数
        shopPage.setSize(shopPageMapper.findSize());
        //开始(末尾)数据是第几行
        shopPage.setStartRow(pageBegin + 1);
        shopPage.setEndRow(pageBegin + pageSize + 1);
        //每页数据条数
        shopPage.setPageSize(pageSize);
        //总页数
        Integer div = shopPage.getSize()/pageSize;
        Integer pages = shopPage.getSize() % pageSize == 0 ? div : div + 1;
        shopPage.setPages(pages);
        //是否是第(最后)一页,是否有前(后)一页
        shopPage.setIsFirstPage(page == 1);
        shopPage.setHasPreviousPage(page != 1);
        shopPage.setIsLastPage(page.equals(pages));
        shopPage.setHasNextPage(!page.equals(pages));
        //查询到的数据
        shopPage.setData(shopPageMapper.findData(pageBegin,pageSize));
        return shopPage;
    }
}

4.功能实现

请求路径:http://localhost:8888/page/shop?page=3&pageSize=5

请求结果:

{
"pageNum":3,
"pageSize":5,
"size":1000,
"startRow":11,
"endRow":16,
"pages":200,
"prePage":2,
"nextPage":4,
"isFirstPage":false,
"isLastPage":false,
"hasPreviousPage":true,
"hasNextPage":true,
"navigatePages":null,
"navigatePageNums":null,
"data":[{"id":11,"name":"小安汽修",
        {"id":12,"name":"大壮副食"},
        {"id":13,"name":"小牛电动"},
        {"id":14,"name":"哈哈笑超市"},
        {"id":15,"name":"包子"}],
"navigateFirstPage":null,
"navigateLastPage":null,
"firstPage":null,
"lastPage":null
}

这样请求的时候只需要传入page(页码)、pageSize(每页数量),就可以将数据和分页信息查询到。

存在的问题:上边的ShopPage、ShopMapper类和ShopPageController类都是跟实体类写死的,也就是跟实体类有很大的耦合性,那这样以后如果要给别的实体类写一个分页查询,还要大量重复这些相近的代码,所以完全可以将pageMapper类和pageController类写成所有实体类都可以使用的,这样再多传入一个动态的参数(也就是实体的名字),就可以实现Page类、PageMapper接口和PageController类的复用,这样就在实现功能的同时降低了代码的耦合性,减少代码。

三、基于mapper.xml的复杂分页查询

上面提到了将分页类和实体类都写在一起了,下面就将它们拆开来,将Page、PageMapper、PageController写成能够被所有类使用的分页功能,下面是实现代码:

1.首先要配置一下xxxMapper.xml文件的地址:

在com....包下面的config文件夹(没有就新建)中写一个CustomMybatisConfig类来对SqlSession进行配置:

import ...

@Configuration
public class CustomMybatisConfig {

    @Autowired
    private DataSource dataSource;

    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);

        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("classpath:.../*.xml");
        sqlSessionFactoryBean.setMapperLocations(resources);

        return sqlSessionFactoryBean;

    }
}

getResources("classpath:.../*.xml")里面要写.xml文件的路径,这个路径也可以这样指定:在application.properties里面添加如下配置用来指定xml文件的存放位置是一样的:

mybatis.mapper-locations=classpath:/mybatis/mapper/*.xml

1.定义Page类

import ...

@Data
public class Page {
    //第几页
    private Integer pageNum;
    //每页数据条数
    private Integer pageSize;
    //总数据条数
    private Integer size;
    //起始(末尾)数据
    private Integer startRow;
    private Integer endRow;
    //总页数
    private Integer pages;
    //上(下)一页页码
    private Integer prePage;
    private Integer nextPage;
    //是否是第(最后)一行
    private Boolean isFirstPage;
    private Boolean isLastPage;
    //有无前(后)页
    private Boolean hasPreviousPage;
    private Boolean hasNextPage;
    private Integer navigatePages;
    private List navigatePageNums;
    //数据数组
    private List<Map<String,Object>> tableData;
    private Integer navigateFirstPage;
    private Integer navigateLastPage;
    //第(最后)一页
    private Integer firstPage;
    private Integer lastPage;

}

2.Mapper接口

import ...

@Mapper
public interface PageMapper {

    List<Map<String,Object>>  selectTableData(String entity, Integer pageBegin, Integer pageSize);

    int selectSize(String entity);
}

这里推荐一个常用的插件:mybatis-helper,可以实现从xxxMapper到XXXMapper.xml方法的快捷跳转,效果如下:

3.pageMapper.xml

新建一个xml文件,按照规范,名字应跟Mapper接口一致,然后将SQL写在xml中。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.....PageMapper">   <!--namespace就是mapper文件的路径,文件名必须跟Dao类名字一致,因为是根据文件名做关联-->

    <select id="selectSize" statementType="STATEMENT" resultType="int" >
        select count(*) from
            ${entity}
    </select>

    <select id="selectTableData" resultType="map" >
        select * from
            ${entity}
        limit
            #{pageBegin}, #{pageSize}
    </select>

</mapper>

4.pageService

import ...

public interface PageService {

    int selectSize(String entity);

    Page paging(String entity, Integer pageNumber, Integer pageSize);

    List<Map<String,Object>> selectTableData(String entity, Integer pageBegin, Integer pageSize);
}

5.pageService的实现类pageServiceImpl

import ...

@Service
public class PageServiceImpl implements PageService {

    @Autowired
    private PageMapper pageMapper;

    @Override
    public int selectSize(String entity) {
        return pageMapper.selectSize(entity);
    }

    @Override
    public Page paging(String entity, Integer pageNumber, Integer pageSize) {
        Page page = new Page();
        Integer pageBegin = (pageNumber - 1) * pageSize;
        //当前页码
        page.setPageNum(pageNumber);
        //前(后)一页页码
        page.setPrePage(pageNumber - 1);
        page.setNextPage(pageNumber + 1);
        //总数据条数
        page.setSize(pageMapper.selectSize(entity));
        //开始(末尾)数据是第几行
        page.setStartRow(pageBegin + 1);
        page.setEndRow(pageBegin + pageSize + 1);
        //每页数据条数
        page.setPageSize(pageSize);
        //总页数
        Integer div = page.getSize() / pageSize;
        Integer pages = page.getSize() % pageSize == 0 ? div : div + 1;
        page.setPages(pages);
        //是否是第(最后)一页,是否有前(后)一页
        page.setIsFirstPage(pageNumber == 1);
        page.setHasPreviousPage(pageNumber != 1);
        page.setIsLastPage(pageNumber.equals(pages));
        page.setHasNextPage(!pageNumber.equals(pages));
        //查询到的数据
        page.setTableData(pageMapper.selectTableData(entity, pageBegin, pageSize));
        return page;
    }

    @Override
    public List<Map<String,Object>> selectTableData(String entity, Integer pageBegin, Integer pageSize) {
        pageBegin = pageBegin - 1;
        return pageMapper.selectTableData(entity,pageBegin,pageSize);
    }
}

6.功能实现

请求路径:http://localhost:8888/page/shop?pageNumber=2&pageSize=10

请求结果:

{"pageNum":2,
"pageSize":10,
"size":1000,
"startRow":11,
"endRow":21,
"pages":100,
"prePage":1,
"nextPage":3,
"isFirstPage":false,
"isLastPage":false,
"hasPreviousPage":true,
"hasNextPage":true,
"navigatePages":null,
"navigatePageNums":null,
"data":[{"id":11,"name":"豆浆油条"},
        {"id":12,"name":"子文包子"},
        {"id":13,"name":"黄河馒头"},
        {"id":14,"name":"长江小笼包"},
        {"id":15,"name":"上海画图图图"},
        {"id":16,"name":"小型制造"},
        {"id":17,"name":"小花"},
        {"id":18,"name":"小明"},
        {"id":19,"name":"小刚"},
        {"id":20,"name":"小吃"}],
"navigateFirstPage":null,
"navigateLastPage":null,
"firstPage":null,
"lastPage":null}

7.可扩展性测试

我们重新写一个类,并且在数据库重新建一个表:

import ...

@Entity
@Data
@Table(name = "product")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @Column(name = "title")
    private String title;

    @Column(name = "description")
    private String description;

    @Column(name = "shopId")
    private Integer shopId;

    @Column(name = "price")
    private String price;
}

在xml中添加sql语句,如下:

<?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">
<!-- 注意:文件名必须跟Dao类名字一致,因为是根据文件名做关联。 -->
<mapper>

    <select id="selectByName" parameterType="String" resultMap="baseResultMap">
        select * from t_user t where t.username = #{username} limit 1
    </select>

</mapper>

这个xml文件跟其它的mybatis配置文件一样,namespace可不写。这里baseResultMap没有看到定义,但是确实存在,因为这个是easymybatis提供的一个内置resultMap。

<resultMap标签>:

resultMap="BaseResultMap"
如果配置了resultMap,返回值统一使用 resultMap=“BaseResultMap”,mybatis会根据查询到的条目数量自动进行判断,如果是一条就返回对象,如果是多条就返回List对象列表。

在TUseroDao.java中添加:

TUser selectByName(@Param("username")String username);

如果有问题,解决方法:相应的model对应的mapping中将resultType改成resultMap即可。

扩展:还有一种方式是easymybatis,easymybatis提供的一些查询方式已经满足大部分的查询需求,但是有些复杂的sql语句还是需要写在xml文件中。easymybatis同样支持将sql语句写在xml中,具体配置如下:

上边的例子是自己封装了的page类和page方法,在增加实体类的同时不再需要写page方法,只要数据库里有相关的表名,就可以直接在路径上改变实体名来查找相应类的分页信息,减少了分页方法与其他方法的耦合,这样每一个类的分页使用的都是同一个Mapper。但是这样的弊端也很明显,自定义程度不高,也就是说如果这些要分页的信息如果都没有where条件,或者where条件相同的话,使用这种自封装的方法是没有问题的,但是如果每一个类的分页信息要求的where条件有很大区别,比如说Person类有按照年龄显示分页的where条件,price类有按照价格显示分页的where条件,那么这种封装的方法想要实现这种不同类的不同where条件的分页时就显得可有可无,因为每加一个这样的where条件,就要在Mapper中写一个这样的SQL语句,这样其实更加大了项目开发成本。更加复杂的分页场景就要考虑使用pagehelper分页插件。

四、基于pagehelper插件的复杂分页查询

1. 导入依赖

pom.xml添加依赖:

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.3</version>
</dependency>

2. 添加配置

在aplication.yml或者application.properties添加配置:

#分页pageHelper
pagehelper:
   helper-dialect: mysql
   reasonable: true
   support-methods-arguments: true

 ·helper-dialect:配置使用哪种数据库语言,不配置的话pageHelper也会自动检测

·reasonable:配置分页参数合理化功能,默认是false。

#启用合理化时,如果pageNum<1会查询第一页,如果pageNum>总页数会查询最后一页;

#禁用合理化时,如果pageNum<1或pageNum>总页数会返回空数据。

·params:为了支持startPage(Object params)方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值; 可以配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值, 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero。

·support-methods-arguments:支持通过Mapper接口参数来传递分页参数,默认值false,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。

3.OrderMapper与orderMapper.xml

import ...;

@Mapper
public interface OrderMapper {
    //查找所有
    List<Order> selectAll();
}
<select id="selectAll" resultType=".../Order">
     select * from order_table
</select>

 4. OrderService与OrderServiceImpl

import ...

public interface OrderService {

    List<Order> selectAll();
    //查找所有按照分页展示
    List<Order> findAllUserByPageF(int pageNum,int pageSize);
    //带分页信息查找所有按照分页展示
    PageInfo<Order> findAllUserByPageS(int pageNum, int pageSize);
}
import ...

@Service
public class OrderServiceImpl implements OrderService {
    @Resource
    private OrderMapper orderMapper;

    @Override
    public List<Order> selectAll(){return orderMapper.selectAll();}

    @Override
    public List<Order> findAllUserByPageF(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return orderMapper.selectAll();
    }

    @Override
    public PageInfo<Order> findAllUserByPageS(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Order> lists = orderMapper.selectAll();
        return new PageInfo<Order>(lists);
    }

}

5.OrderController

import ...

@RestController
@RequestMapping("order")
public class OrderController {

    @Resource
    private OrderService orderService;

    @GetMapping("/all")
    public List<Order> selectAll(){
        return this.orderService.selectAll();
    }

    @GetMapping("/page")
    public List<Order> selectAllByPage(int pageNum,int pageSize){
        return orderService.findAllUserByPageF(pageNum,pageSize);
    }

    @GetMapping("/pageandinfo")
    public PageInfo<Order> testPageHelper1(int pageNum,int pageSize){
        return orderService.findAllUserByPageS(pageNum,pageSize);
    }
}

6.功能实现

请求路径:http://localhost:8888/order/page?pageNum=3&pageSize=6

请求结果:

{[{"id":13,"name":"豆浆油条"},
 {"id":14,"name":"子文包子"},
 {"id":15,"name":"黄河馒头"},
 {"id":16,"name":"长江小笼包"},
 {"id":17,"name":"上海画图图图"},
 {"id":18,"name":"小型制造"}]

请求路径:http://localhost:8888/order/page?pageNum=3&pageSize=6http://localhost:8888/order/pageandinfo?pageNum=2&pageSize=3

请求结果:

 
{"pageNum":2,
"pageSize":3,
"size":3,
"startRow":4,
"endRow":6,
"total":6,
"pages":2,
"list":[{"id":13,"name":"豆浆油条"},  
        {"id":14,"name":"子文包子"},  
        {"id":15,"name":"黄河馒头"},],
"prePage":1,
"nextPage":0,
"isFirstPage":false,
"isLastPage":true,
"hasPreviousPage":true,
"hasNextPage":false,
"navigatePages":8,
"navigatepageNums":[1,2],
"navigateFirstPage":1,
"navigateLastPage":2,
"firstPage":1,
"lastPage":2}

7.Mybatis 分页插件 Pagehelper 的 PageInfo 字段属性解释

pageNum=1当前页码
pageSize=1每页个数
size=1当前页个数
startRow=1由第几条开始
endRow=1到第几条结束
total=3总条数
pages=3总页数
list= XXXX查出来的数据集合
prePage=0上一页
nextPage=2下一页
isFirstPage=true是否为首页
isLastPage=false是否为尾页
hasPreviousPage=false是否有上一页
hasNextPage=true是否有下一页
navigatePages=8每页显示的页码个数
navigateFirstPage=1首页
navigateLastPage=3尾页
navigatepageNums=[1, 2, 3]}页码数

五、MybtisPlus插件自动分页配置

1、引入依赖

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

2、MybatisPlusConfig配置文件

@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
}

3、项目中各层具体写法:

Mapper.xml中的sql正常写即可:

<select id="getAll" resultMap="BaseResultMap" >
     select * from staff_t
</select>

xxxMapper中传入page,注意这里的Page的包是mybatisplus的依赖包里面的:

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
List<StaffPO> GetAllByPage(Page page);

xxxService和xxxServiceImpl中传入page:

Page<StaffPO> getAll(Page page);
@Override
public Page<staffPO> getAll(Page page) {
     return xxxMapper.getAll(page);
}

 xxxController中传入page和VO:

public Page<staffPO> getAll(int pageNum,int pageSize) {
        Page<staffVO> page = new Page<>(pageNum,pageSize);
        return xxxService.getAll(page);
    }

  • 25
    点赞
  • 140
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Mybatis分页查询有两种方式,逻辑分页和物理分页。 逻辑分页是通过使用RowBounds类来实现的。在逻辑分页中,首先将所有的结果查询出来,然后通过计算offset和limit,只返回部分结果。这种方式不会在SQL语句中添加limit关键字。具体的原理可以参考《Mybatis逻辑分页原理解析RowBounds》这篇文章。 物理分页是直接在SQL语句中添加limit关键字来限制返回结果的数量。这种方式会直接在数据库中进行分页操作,只返回需要的结果集。一种常见的实现方式是在查询方法名中约定为“findPage”,然后调用分页插件进行分页查询,并将分页信息封装到统一的接口中。你可以查看《MyBatis分页查询助手源代码》了解更多细节。 总结起来,Mybatis分页查询可以通过逻辑分页和物理分页两种方式来实现,具体选择哪种方式取决于你的需求和业务场景。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Mybatis分页查询](https://blog.csdn.net/weixin_41835612/article/details/83713846)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [MyBatis分页查询助手源代码](https://download.csdn.net/download/qq_37647812/88228840)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肆〇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值