本課程全面講解了Mybatis框架的使用,從快速入門到原理分析再到實(shí)戰(zhàn)應(yīng)用。每一個(gè)知識點(diǎn)都有案例進(jìn)行演示學(xué)習(xí),最終通過學(xué)習(xí)你將全面掌握,從而使Mybatis的開發(fā)更加的高效,系統(tǒng)學(xué)習(xí)
通過項(xiàng)目的開發(fā)大家應(yīng)該能發(fā)現(xiàn),單表的CRUD功能代碼重復(fù)度很高,也沒有什么難度。而這部分代碼量往往比較大,開發(fā)起來比較費(fèi)時(shí)。
因此,目前企業(yè)中都會使用一些組件來簡化或省略單表的CRUD開發(fā)工作。目前在國內(nèi)使用較多的一個(gè)組件就是MybatisPlus.
MybatisPlus 擴(kuò)展功能 代碼生成 邏輯刪除 通用枚舉 字段類型處理器 配置加密_軟工菜雞的博客-CSDN博客
4.插件功能
MybatisPlus提供了很多的插件功能,進(jìn)一步拓展其功能。目前已有的插件有:
-
PaginationInnerInterceptor
:自動(dòng)分頁 -
TenantLineInnerInterceptor
:多租戶 -
DynamicTableNameInnerInterceptor
:動(dòng)態(tài)表名 -
OptimisticLockerInnerInterceptor
:樂觀鎖 -
IllegalSQLInnerInterceptor
:sql 性能規(guī)范 -
BlockAttackInnerInterceptor
:防止全表更新與刪除
注意:
使用多個(gè)分頁插件的時(shí)候需要注意插件定義順序,建議使用順序如下:
- 多租戶,動(dòng)態(tài)表名
- 分頁,樂觀鎖
- sql 性能規(guī)范,防止全表更新與刪除
這里我們以分頁插件為里來學(xué)習(xí)插件的用法。
4.1.分頁插件
在未引入分頁插件的情況下,MybatisPlus
是不支持分頁功能的,IService
和BaseMapper
中的分頁方法都無法正常起效。
所以,我們必須配置分頁插件。
4.1.1.配置分頁插件
在項(xiàng)目中新建一個(gè)配置類:
其代碼如下:
package com.itheima.mp.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
// 初始化核心插件
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分頁插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
4.1.2.分頁API
編寫一個(gè)分頁查詢的測試:
@Test
void testPageQuery() {
// 1.分頁查詢,new Page()的兩個(gè)參數(shù)分別是:頁碼、每頁大小
Page<User> p = userService.page(new Page<>(2, 2));
// 2.總條數(shù)
System.out.println("total = " + p.getTotal());
// 3.總頁數(shù)
System.out.println("pages = " + p.getPages());
// 4.數(shù)據(jù)
List<User> records = p.getRecords();
records.forEach(System.out::println);
}
運(yùn)行的SQL如下:
這里用到了分頁參數(shù),Page,即可以支持分頁參數(shù),也可以支持排序參數(shù)。常見的API如下:
int pageNo = 1, pageSize = 5;
// 分頁參數(shù)
Page<User> page = Page.of(pageNo, pageSize);
// 排序參數(shù), 通過OrderItem來指定
page.addOrder(new OrderItem("balance", false));
userService.page(page);
4.2.通用分頁實(shí)體
現(xiàn)在要實(shí)現(xiàn)一個(gè)用戶分頁查詢的接口,接口規(guī)范如下:
參數(shù) |
說明 |
請求方式 |
GET |
請求路徑 |
/users/page |
請求參數(shù) |
```json |
{ |
|
"pageNo": 1, |
|
"pageSize": 5, |
|
"sortBy": "balance", |
|
"isAsc": false |
|
} |
|
| 返回值 | ```json
{
"total": 100006,
"pages": 50003,
"list": [
{
"id": 1685100878975279298,
"username": "user_9****",
"info": {
"age": 24,
"intro": "英文老師",
"gender": "female"
},
"status": "正常",
"balance": 2000
},
{
"id": 1685100878975279299,
"username": "user_9****",
"info": {
"age": 24,
"intro": "英文老師",
"gender": "female"
},
"status": "正常",
"balance": 2000
}
]
}
|
| 特殊說明 | ?如果排序字段為空,默認(rèn)按照更新時(shí)間排序
?排序字段不為空,則按照排序字段排序 |
這里需要定義3個(gè)實(shí)體:
-
PageQuery
:分頁查詢條件的實(shí)體,包含分頁、排序參數(shù) -
PageDTO
:分頁結(jié)果實(shí)體,包含總條數(shù)、總頁數(shù)、當(dāng)前頁數(shù)據(jù) -
UserVO
:用戶頁面視圖實(shí)體
接下來我們就按照WEB開發(fā)的過程來實(shí)現(xiàn)這個(gè)接口。
首先,我們在項(xiàng)目中引入spring-boot-starter-web
依賴:
<!-- web依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- hutool 工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.11</version>
</dependency>
然后,按alt+8
打開service
控制臺,然后添加一個(gè)SpringBoot
啟動(dòng)項(xiàng):
彈窗中選擇Spring Boot
:
彈窗中填寫信息:
其中不要忘了配置我們之前添加的數(shù)據(jù)加密的秘鑰。
4.2.1.實(shí)體
首先是請求參數(shù)的PageQuery
實(shí)體:
PageQuery
是前端提交的查詢參數(shù),一般包含四個(gè)屬性:
-
pageNo
:頁碼 -
pageSize
:每頁數(shù)據(jù)條數(shù) -
sortBy
:排序字段 -
isAsc
:是否升序
package com.itheima.mp.domain.query;
import lombok.Data;
@Data
public class PageQuery {
private Integer pageNo;
private Integer pageSize;
private String sortBy;
private Boolean isAsc;
}
然后我們定義一個(gè)UserVO
實(shí)體:
代碼如下:
package com.itheima.mp.domain.vo;
import com.itheima.mp.domain.po.UserInfo;
import com.itheima.mp.enums.UserStatus;
import lombok.Data;
@Data
public class UserVO {
/**
* 用戶id
*/
private Long id;
/**
* 用戶名
*/
private String username;
/**
* 詳細(xì)信息
*/
private UserInfo info;
/**
* 使用狀態(tài)(1正常 2凍結(jié))
*/
private UserStatus status;
/**
* 賬戶余額
*/
private Integer balance;
}
最后,則是分頁實(shí)體PageDTO:
代碼如下:
package com.itheima.mp.domain.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageDTO<T> {
private Integer total;
private Integer pages;
private List<T> list;
}
4.2.2.開發(fā)接口
我們定義一個(gè)UserController
,在controller
中我們定義分頁查詢用戶的接口:
package com.itheima.mp.controller;
import com.itheima.mp.domain.dto.PageDTO;
import com.itheima.mp.domain.query.PageQuery;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("/page")
public PageDTO<UserVO> queryUserByPage(PageQuery query){
return userService.queryUserByPage(query);
}
}
然后在UserService
中創(chuàng)建queryUserByPage
方法:
PageDTO<UserVO> queryUserByPage(PageQuery query);
接下來,在UserServiceImpl中實(shí)現(xiàn)該方法:
@Override
public PageDTO<UserVO> queryUserByPage(PageQuery query) {
// 1.構(gòu)建條件
// 1.1.分頁條件
Page<User> page = Page.of(query.getPageNo(), query.getPageSize());
// 1.2.排序條件
if (query.getSortBy() != null) {
page.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc()));
}else{
// 默認(rèn)按照更新時(shí)間排序
page.addOrder(new OrderItem("update_time", false));
}
// 2.查詢
page(page);
// 3.數(shù)據(jù)非空校驗(yàn)
List<User> records = page.getRecords();
if (records == null || records.size() <= 0) {
// 無數(shù)據(jù),返回空結(jié)果
return new PageDTO<>(page.getTotal(), page.getPages(), Collections.emptyList());
}
// 4.有數(shù)據(jù),轉(zhuǎn)換
List<UserVO> list = BeanUtil.copyToList(records, UserVO.class);
// 5.封裝返回
return new PageDTO<UserVO>(page.getTotal(), page.getPages(), list);
}
最后,為了讓UserStatus枚舉可以展示為文字描述,再給UserStatus中的desc字段添加@JsonValue
注解:
啟動(dòng)項(xiàng)目,在頁面查看:
4.2.3.改造PageQuery實(shí)體
在剛才的代碼中,從PageQuery
到MybatisPlus
的Page
之間轉(zhuǎn)換的過程還是比較麻煩的。
我們完全可以在PageQuery
這個(gè)實(shí)體中定義一個(gè)工具方法,簡化開發(fā)。
像這樣:
package com.itheima.mp.domain.query;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
@Data
public class PageQuery {
private Integer pageNo;
private Integer pageSize;
private String sortBy;
private Boolean isAsc;
public <T> Page<T> toMpPage(OrderItem ... orders){
// 1.分頁條件
Page<T> p = Page.of(pageNo, pageSize);
// 2.排序條件
// 2.1.先看前端有沒有傳排序字段
if (sortBy != null) {
p.addOrder(new OrderItem(sortBy, isAsc));
return p;
}
// 2.2.再看有沒有手動(dòng)指定排序字段
if(orders != null){
p.addOrder(orders);
}
return p;
}
public <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc){
return this.toMpPage(new OrderItem(defaultSortBy, isAsc));
}
public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() {
return toMpPage("create_time", false);
}
public <T> Page<T> toMpPageDefaultSortByUpdateTimeDesc() {
return toMpPage("update_time", false);
}
}
這樣我們在開發(fā)也時(shí)就可以省去對從PageQuery
到Page
的的轉(zhuǎn)換:
// 1.構(gòu)建條件
Page<User> page = query.toMpPageDefaultSortByCreateTimeDesc();
4.2.4.改造PageDTO實(shí)體
在查詢出分頁結(jié)果后,數(shù)據(jù)的非空校驗(yàn),數(shù)據(jù)的vo轉(zhuǎn)換都是模板代碼,編寫起來很麻煩。
我們完全可以將其封裝到PageDTO的工具方法中,簡化整個(gè)過程:
package com.itheima.mp.domain.dto;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageDTO<V> {
private Long total;
private Long pages;
private List<V> list;
/**
* 返回空分頁結(jié)果
* @param p MybatisPlus的分頁結(jié)果
* @param <V> 目標(biāo)VO類型
* @param <P> 原始PO類型
* @return VO的分頁對象
*/
public static <V, P> PageDTO<V> empty(Page<P> p){
return new PageDTO<>(p.getTotal(), p.getPages(), Collections.emptyList());
}
/**
* 將MybatisPlus分頁結(jié)果轉(zhuǎn)為 VO分頁結(jié)果
* @param p MybatisPlus的分頁結(jié)果
* @param voClass 目標(biāo)VO類型的字節(jié)碼
* @param <V> 目標(biāo)VO類型
* @param <P> 原始PO類型
* @return VO的分頁對象
*/
public static <V, P> PageDTO<V> of(Page<P> p, Class<V> voClass) {
// 1.非空校驗(yàn)
List<P> records = p.getRecords();
if (records == null || records.size() <= 0) {
// 無數(shù)據(jù),返回空結(jié)果
return empty(p);
}
// 2.數(shù)據(jù)轉(zhuǎn)換
List<V> vos = BeanUtil.copyToList(records, voClass);
// 3.封裝返回
return new PageDTO<>(p.getTotal(), p.getPages(), vos);
}
/**
* 將MybatisPlus分頁結(jié)果轉(zhuǎn)為 VO分頁結(jié)果,允許用戶自定義PO到VO的轉(zhuǎn)換方式
* @param p MybatisPlus的分頁結(jié)果
* @param convertor PO到VO的轉(zhuǎn)換函數(shù)
* @param <V> 目標(biāo)VO類型
* @param <P> 原始PO類型
* @return VO的分頁對象
*/
public static <V, P> PageDTO<V> of(Page<P> p, Function<P, V> convertor) {
// 1.非空校驗(yàn)
List<P> records = p.getRecords();
if (records == null || records.size() <= 0) {
// 無數(shù)據(jù),返回空結(jié)果
return empty(p);
}
// 2.數(shù)據(jù)轉(zhuǎn)換
List<V> vos = records.stream().map(convertor).collect(Collectors.toList());
// 3.封裝返回
return new PageDTO<>(p.getTotal(), p.getPages(), vos);
}
}
最終,業(yè)務(wù)層的代碼可以簡化為:
@Override
public PageDTO<UserVO> queryUserByPage(PageQuery query) {
// 1.構(gòu)建條件
Page<User> page = query.toMpPageDefaultSortByCreateTimeDesc();
// 2.查詢
page(page);
// 3.封裝返回
return PageDTO.of(page, UserVO.class);
}
如果是希望自定義PO到VO的轉(zhuǎn)換過程,可以這樣做:
@Override
public PageDTO<UserVO> queryUserByPage(PageQuery query) {
// 1.構(gòu)建條件
Page<User> page = query.toMpPageDefaultSortByCreateTimeDesc();
// 2.查詢
page(page);
// 3.封裝返回
return PageDTO.of(page, user -> {
// 拷貝屬性到VO
UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
// 用戶名脫敏
String username = vo.getUsername();
vo.setUsername(username.substring(0, username.length() - 2) + "**");
return vo;
});
}
最終查詢的結(jié)果如下:
非常感謝您閱讀到這里,創(chuàng)作不易!如果這篇文章對您有幫助,希望能留下您的點(diǎn)贊?? 關(guān)注?? 收藏 ??評論??感謝支持?。。?/strong>
聽說 三連能夠給人 帶來好運(yùn)!更有可能年入百w,進(jìn)入大廠,上岸文章來源:http://www.zghlxwxcb.cn/news/detail-702508.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-702508.html
到了這里,關(guān)于MybatisPlus插件功能詳細(xì)介紹 自動(dòng)分頁 通用分頁實(shí)體的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!