【Mybatis plus 3.2】怎么操作?看看我!(update、limit、between)

本文详细介绍了如何在Spring Boot项目中使用MyBatis Plus进行数据库操作,包括依赖添加、配置、Mapper接口定义及增删改查的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

必须是springboot工程

在pom.xml中添加
<dependency>
   <groupId>com.baomidou</groupId>
   <artifactId>mybatis-plus-boot-starter</artifactId>
   <version>3.2.0</version>
</dependency>
配置application.yml
# DataSource Config
spring:
  datasource:
    driver-class-name: org.h2.Driver
    schema: classpath:db/schema-h2.sql
    data: classpath:db/data-h2.sql
    url: jdbc:h2:mem:test
    username: root
    password: test

Mapper

写一个接口继承BaseMapper

public interface CategoryMapper extends BaseMapper<Category> {

}

对数据库操作

insert 插入数据

注意:类名、表名、类属性名、列名 尽量都小写比如"username"和数据库表列名"username"(mysql数据库不区分大小写)可以刚好对应上,如果你用"userName",那么数据库列名就要是"user_name"。

categoryMapper.insert(category);

update更新数据

1.自定义更新

public void updWrap() {
        User user=new User();
        user.setAddress("广州");
        user.setAge(23);
        userMapper.update(user,new UpdateWrapper<User>().eq("name_","a").or().eq("name_","b"));
}

2.按id进行更新

public void upd() {
        User user=new User();
        user.setId(10086);
        user.setName("lll");
        user.setAge(23);
        userMapper.updateById(user);
}

select 查询操作

1.全部查询(select * from category)

List<Category> categories = categoryMapper.selectList(null);

2.按条件查询(select * from category where flag=1)

QueryWrapper queryWrapper1=new QueryWrapper();
queryWrapper1.eq("flag",1);
categories = categoryMapper.selectList(queryWrapper1);

3.按范围查询(select * from category where id between 0 and 500)

QueryWrapper queryWrapper1=new QueryWrapper();
queryWrapper1.between("id",0,500);
categories = categoryMapper.selectList(queryWrapper1);

4.limit限制数量查询(select * from category limit 0,10)
limit “起始位置”,“条数”
例如 limit 2,5意思是从第3行开始取共5行数据

QueryWrapper<Product> queryWrapper=new QueryWrapper<>();
String sql="limit "+start+",10";
queryWrapper.last(sql);
//从"start"开始。查询"10"条
products = productMapper.selectList(queryWrapper);

删除操作

删除操作我没有使用过,别人博客:
设置逻辑删除

mybatis-plus:
  mapper-locations: classpath:/mapper/**/*.xml
  global-config:
      refresh: true # 刷新xml文件
      db-config:
            logic-delete-value: 1 #默认值1
            logic-not-delete-value: 0 #默认值0

这里指定逻辑删除 删除标记 为1 表示删除 为0 表示正常

userMapper.deleteById(10086);
<think>我们参考引用[1]和引用[2]的内容,特别是引用[2]中关于分页参数模型设计和高级组合分页参数的思路。目标:实现一个统一封装的分页查询,支持分页、排序、时间筛选。步骤:1.设计分页参数模型(PageParam)及其扩展类(支持排序、时间筛选)。2.使用MyBatisPlus的分页拦截器(PaginationInterceptor)进行物理分页。3.在Service层中根据不同的参数构建查询条件。根据引用[2]的设计,我们可以设计如下参数类:基础分页参数(PageParam):-页码(pageNo)-每页大小(pageSize)可排序的分页参数(SortablePageParam):-继承PageParam-增加排序字段列表(List<SortingField>)可时间筛选的分页参数(FilterPageParam):-继承PageParam-增加时间筛选字段列表(List<FilteringField>)同时支持排序和筛选的参数(SearchPageParam):-可以同时继承SortablePageParam和FilterPageParam,但Java不支持多继承,所以我们可以设计为:SearchPageParamextendsSortablePageParam,然后内部包含一个FilterPageParam的字段,或者直接再创建一个同时包含两者的类。但引用[2]中采用了继承关系,并且有一个组合类(SearchPageParam)同时支持排序和筛选。我们可以这样设计:具体实现:1.基础分页参数类(PageParam)2.可排序参数类(SortablePageParam)继承PageParam,增加排序字段3.时间筛选参数类(TimeFilterPageParam)继承PageParam,增加时间筛选字段4.同时支持排序和时间筛选的参数类(SortAndTimeFilterPageParam)可以继承SortablePageParam,并增加时间筛选字段(或者单独设计一个类同时包含两者)但是,为了更好的扩展性,我们可以采用组合的方式,即:-基础分页参数(PageParam)包含基本分页信息。-排序参数(SortingParam)作为一个独立的类,包含排序字段列表。-时间筛选参数(TimeFilterParam)作为一个独立的类,包含时间筛选字段列表。然后在高级分页参数中组合这些参数。但引用[2]采用了继承,我们按照引用[2]的思路来实现。然而,引用[2]中的类设计如下:PageParam(基础分页)|SortablePageParam(增加了排序字段)|FilterPageParam(增加了时间筛选字段)但是这里FilterPageParam是直接继承PageParam的?还是继承SortablePageParam?引用[2]中画的是继承关系,但文字描述是组合。实际上,引用[2]中展示的是:PageParam├──SortablePageParam-->支持排序├──FilterPageParam-->支持筛选└──SearchPageParam-->同时支持排序+筛选(这里应该是继承某个类并组合另一个?)由于Java是单继承,所以SearchPageParam可以继承其中一个,然后包含另一个。但是引用[2]没有给出SearchPageParam的具体代码。我们调整设计:使用组合代替继承来支持多种条件的组合。重新设计:1.基础分页参数(PageParam)包含pageNo和pageSize。2.排序参数(SortingField)表示单个排序字段,包含字段名和排序方向(asc/desc)。3.时间筛选参数(TimeFilterField)表示单个时间筛选字段,包含字段名和时间范围(开始时间和结束时间)。然后,我们创建一个高级分页参数类(AdvancedPageParam):-包含PageParam(或者直接包含pageNo和pageSize,但为了复用,我们可以包含一个PageParam对象)-包含一个排序字段列表(List<SortingField>)-包含一个时间筛选字段列表(List<TimeFilterField>)这样,我们就可以在一个参数类中同时支持分页、排序和时间筛选。但是,为了与引用[2]的命名保持一致,我们也可以这样:publicclassPageQueryParam{privatePageParampageParam;//分页参数privateList<SortingField>sortingFields;//排序字段privateList<TimeFilterField>timeFilterFields;//时间筛选字段}不过,引用[2]中也有一个SearchPageParam,它同时支持排序和筛选。我们可以直接使用这个类。由于引用[2]没有给出完整代码,我们按照其思路自己实现。下面我们按照组合的方式设计参数类:参数类设计:1.PageParam(基础分页参数)2.SortingField(排序字段)3.TimeFilterField(时间范围筛选字段)然后,我们创建一个高级查询参数类(AdvancedPageQueryParam),它包含:-PageParampageParam-List<SortingField>sorts-List<TimeFilterField>timeFilters但是,为了简化,我们也可以将分页参数直接放在AdvancedPageQueryParam中作为属性(而不是嵌套一个对象),这样使用起来更方便。我们选择直接包含分页参数:publicclassAdvancedPageQueryParam{//分页参数privateIntegerpageNo=1;privateIntegerpageSize=10;//排序字段列表privateList<SortingField>sorts;//时间筛选字段列表privateList<TimeFilterField>timeFilters;}这样设计简单直接。但是,为了复用,我们可以将分页参数提取出来,这样其他地方如果只需要分页,可以单独使用PageParam。因此,我们按照引用[2]的思路,设计一个包含分页参数并扩展了其他参数的高级参数类。这里我们采用另一种方式:让高级参数类继承PageParam,然后增加排序和时间筛选字段。这样高级参数类就包含了分页参数,同时扩展了其他条件。所以:publicclassAdvancedPageQueryParamextendsPageParam{privateList<SortingField>sorts;privateList<TimeFilterField>timeFilters;}这样,AdvancedPageQueryParam就拥有了pageNo和pageSize,以及排序和时间筛选字段。接下来,我们需要在Service层中根据这个参数构建QueryWrapper。步骤:1.创建Page对象(MyBatisPlus的分页对象)用于分页。2.构建QueryWrapper,根据排序字段和时间筛选字段添加条件。示例代码:首先,定义参数类:注意:这里使用Lombok简化代码。1.PageParam.java```javaimportlombok.Data;importjavax.validation.constraints.Min;importjavax.validation.constraints.NotNull;importjava.io.Serializable;@DatapublicclassPageParamimplementsSerializable{@NotNull(message="页码不能为空")@Min(value=1,message="页码最小为1")privateIntegerpageNo=1;@NotNull(message="每页条数不能为空")@Min(value=1,message="每页条数最小为1")privateIntegerpageSize=10;}```2.SortingField.java```javaimportlombok.Data;@DatapublicclassSortingField{publicstaticfinalStringORDER_ASC="asc";publicstaticfinalStringORDER_DESC="desc";privateStringfield;//排序字段privateStringorder;//排序方向:asc/desc}```3.TimeFilterField.java```javaimportlombok.Data;importjava.time.LocalDateTime;@DatapublicclassTimeFilterField{privateStringfield;//时间字段privateLocalDateTimestartTime;//开始时间privateLocalDateTimeendTime;//结束时间}```4.AdvancedPageQueryParam.java```javaimportlombok.Data;importlombok.EqualsAndHashCode;importjava.util.List;@Data@EqualsAndHashCode(callSuper=true)publicclassAdvancedPageQueryParamextendsPageParam{privateList<SortingField>sorts;//排序字段列表privateList<TimeFilterField>timeFilters;//时间筛选字段列表}```然后,在Service层使用:假设我们有一个UserService,需要根据时间范围(比如创建时间)和排序(比如按创建时间倒序)来分页查询用户。示例Service方法:```javaimportcom.baomidou.mybatisplus.core.conditions.query.QueryWrapper;importcom.baomidou.mybatisplus.core.metadata.IPage;importcom.baomidou.mybatisplus.extension.plugins.pagination.Page;importorg.springframework.stereotype.Service;importjavax.annotation.Resource;importjava.util.List;@ServicepublicclassUserServiceImplimplementsUserService{@ResourceprivateUserMapperuserMapper;publicIPage<User>queryAdvanced(AdvancedPageQueryParamparam){//1.构建分页对象Page<User>page=newPage<>(param.getPageNo(),param.getPageSize());//2.构建查询条件QueryWrapper<User>queryWrapper=newQueryWrapper<>();//3.处理时间筛选条件if(param.getTimeFilters()!=null&&!param.getTimeFilters().isEmpty()){for(TimeFilterFieldtimeFilter:param.getTimeFilters()){//如果开始时间和结束时间都不为空,则添加between条件if(timeFilter.getStartTime()!=null&&timeFilter.getEndTime()!=null){queryWrapper.between(timeFilter.getField(),timeFilter.getStartTime(),timeFilter.getEndTime());}//如果只有开始时间,则添加>=条件elseif(timeFilter.getStartTime()!=null){queryWrapper.ge(timeFilter.getField(),timeFilter.getStartTime());}//如果只有结束时间,则添加<=条件elseif(timeFilter.getEndTime()!=null){queryWrapper.le(timeFilter.getField(),timeFilter.getEndTime());}}}//4.处理排序条件if(param.getSorts()!=null&&!param.getSorts().isEmpty()){for(SortingFieldsort:param.getSorts()){if(SortingField.ORDER_ASC.equalsIgnoreCase(sort.getOrder())){queryWrapper.orderByAsc(sort.getField());}elseif(SortingField.ORDER_DESC.equalsIgnoreCase(sort.getOrder())){queryWrapper.orderByDesc(sort.getField());}}}//5.执行分页查询returnuserMapper.selectPage(page,queryWrapper);}}```注意:这里我们假设UserMapper继承了MyBatisPlus的BaseMapper。另外,我们还需要配置MyBatisPlus的分页拦截器:```javaimportcom.baomidou.mybatisplus.annotation.DbType;importcom.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;importcom.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassMybatisPlusConfig{@BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptor=newMybatisPlusInterceptor();interceptor.addInnerInterceptor(newPaginationInnerInterceptor(DbType.MYSQL));//根据数据库类型选择returninterceptor;}}```这样,我们就实现了统一封装的高级分页查询,支持分页、排序和时间筛选。使用示例:前端传入参数示例(JSON):```json{"pageNo":1,"pageSize":10,"sorts":[{"field":"create_time","order":"desc"}],"timeFilters":[{"field":"create_time","startTime":"2023-01-01T00:00:00","endTime":"2023-12-31T23:59:59"}]}```这个参数会被映射到AdvancedPageQueryParam对象,然后调用queryAdvanced方法即可。注意事项:-时间格式:前端传递的时间字符串需要能被转换为LocalDateTime(例如ISO格式)。-字段名:这里的字段名对应数据库的列名(注意大小写和下划线)。-安全性:在实际应用中,需要对字段名进行安全检查,防止SQL注入。MyBatisPlus的QueryWrapper在设置字段名时是使用字符串拼接的,所以需要确保字段名是安全的(比如只允许特定的字段名)。为了安全,我们可以对字段名进行校验,例如只允许某些预定义的字段进行排序或时间筛选。可以在Service层添加校验逻辑。例如,在构建查询条件之前,检查排序字段和时间筛选字段是否在允许的字段列表中。改进后的排序处理:```java//允许排序的字段列表Set<String>allowedSortFields=newHashSet<>(Arrays.asList("create_time","update_time","name"));if(param.getSorts()!=null&&!param.getSorts().isEmpty()){for(SortingFieldsort:param.getSorts()){//检查字段是否允许排序if(!allowedSortFields.contains(sort.getField())){thrownewIllegalArgumentException("不允许按字段["+sort.getField()+"]排序");}if(SortingField.ORDER_ASC.equalsIgnoreCase(sort.getOrder())){queryWrapper.orderByAsc(sort.getField());}elseif(SortingField.ORDER_DESC.equalsIgnoreCase(sort.getOrder())){queryWrapper.orderByDesc(sort.getField());}}}```同样,对时间筛选字段也可以做类似的校验。这样,我们就完成了一个安全且灵活的高级分页查询封装。总结:-设计了分页参数、排序参数、时间筛选参数以及组合参数类。-在Service层根据参数动态构建查询条件。-使用MyBatisPlus的分页拦截器实现物理分页。-增加了字段安全性校验。以上代码示例供参考,可根据实际需求调整。</think>### MyBatis Plus 高级分页统一封装实现 下面我将详细说明如何实现支持分页、排序和时间筛选的统一封装方案,并提供完整示例代码。该方案基于 MyBatis Plus 的分页拦截器机制[^1],采用面向扩展的参数设计[^2]。 #### 一、核心参数模型设计 ```java // 基础分页参数(必须) @Data public class PageParam { @NotNull @Min(1) private Integer pageNo = 1; @NotNull @Min(1) @Max(200) private Integer pageSize = 10; } // 排序字段模型(可选) @Data public class SortingField { public static final String ORDER_ASC = "asc"; public static final String ORDER_DESC = "desc"; @NotBlank private String field; // 排序字段名 @Pattern(regexp = "asc|desc", flags = Pattern.Flag.CASE_INSENSITIVE) private String order = ORDER_DESC; // 排序方向 } // 时间筛选模型(可选) @Data @NoArgsConstructor @AllArgsConstructor public class TimeFilterField { @NotBlank private String field; // 时间字段名 @Size(min = 1, max = 2) private LocalDateTime[] range; // 时间范围 [start, end] } // 高级分页参数(组合所有功能) @Data @EqualsAndHashCode(callSuper = true) public class AdvancedPageParam extends PageParam { private List<SortingField> sorts; // 排序字段列表 private List<TimeFilterField> timeFilters; // 时间筛选列表 } ``` #### 二、统一分页处理工具类 ```java public class PageQueryUtil { /** * 构建带排序和时间筛选的QueryWrapper * @param param 高级分页参数 * @param entityClass 实体类型 * @return 配置好的QueryWrapper */ public static <T> QueryWrapper<T> buildWrapper(AdvancedPageParam param, Class<T> entityClass) { QueryWrapper<T> wrapper = new QueryWrapper<>(); // 处理排序条件 if (CollectionUtils.isNotEmpty(param.getSorts())) { param.getSorts().forEach(sort -> { if (SortingField.ORDER_ASC.equalsIgnoreCase(sort.getOrder())) { wrapper.orderByAsc(getColumnName(sort.getField(), entityClass)); } else { wrapper.orderByDesc(getColumnName(sort.getField(), entityClass)); } }); } // 处理时间筛选 if (CollectionUtils.isNotEmpty(param.getTimeFilters())) { param.getTimeFilters().forEach(filter -> { String column = getColumnName(filter.getField(), entityClass); LocalDateTime[] range = filter.getRange(); if (range.length == 1) { wrapper.ge(column, range[0]); // 单点时间:大于等于 } else if (range.length == 2) { wrapper.between(column, range[0], range[1]); // 时间区间 } }); } return wrapper; } // 安全获取数据库列名(防止SQL注入) private static <T> String getColumnName(String field, Class<T> entityClass) { // 实际实现应使用反射获取实体字段对应的列名 // 此处简化演示,生产环境建议使用MyBatis Plus的TableInfoHelper return StringUtils.camelToUnderline(field); } } ``` #### 三、Service层实现示例 ```java @Service @RequiredArgsConstructor public class UserServiceImpl implements UserService { private final UserMapper userMapper; @Override public IPage<User> queryByAdvancedParam(AdvancedPageParam param) { // 1. 构建分页对象 Page<User> page = new Page<>(param.getPageNo(), param.getPageSize()); // 2. 构建动态查询条件 QueryWrapper<User> wrapper = PageQueryUtil.buildWrapper(param, User.class); // 3. 执行分页查询 return userMapper.selectPage(page, wrapper); } } ``` #### 四、Controller层调用示例 ```java @RestController @RequestMapping("/users") public class UserController { private final UserService userService; @PostMapping("/advanced-query") public R<IPage<User>> advancedQuery(@Valid @RequestBody AdvancedPageParam param) { return R.success(userService.queryByAdvancedParam(param)); } } ``` #### 五、前端请求示例(JSON) ```json { "pageNo": 2, "pageSize": 15, "sorts": [ {"field": "createTime", "order": "desc"}, {"field": "username", "order": "asc"} ], "timeFilters": [ { "field": "createTime", "range": ["2023-01-01T00:00:00", "2023-12-31T23:59:59"] }, { "field": "updateTime", "range": ["2023-06-01T00:00:00"] // 单时间点表示 >= } ] } ``` ### 关键实现说明: 1. **分页核心机制** MyBatis Plus 通过 `PaginationInterceptor` 拦截 SQL 自动添加 `LIMIT` 分页语句[^1] 2. **安全处理**: - 字段名转换:将驼峰字段转为下划线列名 - 正则校验:排序方向只允许 `asc/desc` - 范围控制:每页条数限制 1-200 3. **动态条件构建**: ```mermaid graph TD A[接收请求参数] --> B{验证参数合法性} B -->|有效| C[构建QueryWrapper] C --> D[添加排序条件] C --> E[添加时间范围条件] D --> F[执行分页查询] E --> F F --> G[返回分页结果] ``` 4. **扩展性设计**: - 可单独使用基础分页(PageParam) - 可组合排序(SortablePageParam) - 可组合时间筛选(TimeFilterPageParam) - 全功能组合(AdvancedPageParam) > **最佳实践建议**: > 1. 在 `getColumnName()` 方法中实现字段白名单校验 > 2. 对时间范围参数进行合理性校验(如结束时间不能早于开始时间) > 3. 使用 Spring Validation 进行参数校验(如 `@Valid` 注解) > 4. 重要操作添加审计日志记录 此方案通过统一参数封装和工具类实现,显著提高了分页查询代码的复用性和可维护性,同时保持高度灵活性[^2]。 --- ### 相关问题 1. **如何防止 MyBatis Plus 分页查询中的 SQL 注入风险?** > 解决方案包括:字段名白名单校验、使用预编译语句、禁用 ${} 拼接等 2. **MyBatis Plus 分页查询性能优化的常见手段有哪些?** > 可考虑:分页语句优化、索引优化、避免 count(1) 的替代方案等 3. **如何实现跨多表的高级分页查询?** > 需要结合 Join 查询和自定义分页 SQL,可使用 MyBatis Plus 的 `selectPage(Page, QueryWrapper)` 重载方法 4. **时间范围查询如何处理时区问题?** > 建议:统一使用 UTC 时间存储,前端按用户时区转换,或使用数据库时区转换函数 5. **分页数据如何高效导出为 Excel?** > 可采用:分批查询写入、异步导出、压缩传输等技术方案 [^1]: MyBatis Plus 的分页拦截器机制会自动处理物理分页语句 [^2]: 通过参数模型继承和组合实现高扩展性的分页设计
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值