??????? 筆者寫這篇博客是因為近期遇到的關于兩者之間的分頁代碼差距,其實之前也遇見過但是沒有去整理這篇博客,但由于還是被困擾了小一會兒時間,所以還是需要加深記憶。其實會看前后端傳參解決這個問題很快、不麻煩。關于這兩個框架的分頁代碼問題主要就是在業(yè)務層和MyBatis的SQL問題。注意:這里我不展示前端接口,需要知道的是前端會傳給后端當前頁(page)以及每頁條數(shù)(size)。后端根據(jù)兩個參數(shù)去實現(xiàn)分頁(limit)。這里最容易踩坑的一個點:在MyBatis的分頁中,(當前頁需要 - 1) * size傳入#{page},而在MyBatis-Plus中的new Page(page,size),則不需要去做運算,在Plus已經做好了這一點。詳情請看下面代碼塊。
MyBatis
??????? 那么關于MyBatis這個半ORM框架來說,SQL還是需要自己去寫在xml中的或者是在注解上實現(xiàn)。這里我就采用xml種實現(xiàn)的方式去實現(xiàn)啦。為了減少代碼量(真實開發(fā)不能這樣的哈),我就將所有業(yè)務代碼都放到控制層中。
引入依賴
<!-- MyBatis框架 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!-- JDBC驅動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
<!-- MyBatis的分頁插件PageHelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.12</version>
</dependency>
修改yml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/table?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml # 對應xml的位置
type-aliases-package: com.chf.entity # 對應namespace的實體類包名
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 日志類型
map-underscore-to-camel-case: true # 字段與屬性的駝峰規(guī)則
# MyBatis的分頁插件 這是最重要的
pagehelper:
helper-dialect: mysql
reasonable: true
support-methods-arguments: true
params: count=countsql
業(yè)務代碼
@RestController
@RequestMapping("/emp")
public class EmpController{
//@Autowired
//private EmpService empService;
// 為了博客簡化代碼量 所以直接調用Dao層接口
@Autowired
private EmpMapper empMapper;
/**
* 分頁查詢
* @param pageNum 當前頁數(shù)
* @param pageSize 每頁條數(shù)
* @return
*/
@GetMapping("/findAll/{page}/{size}")
public R findAll(@PathVariable("page") Integer pageNum, @PathVariable("size") Integer pageSize){
Integer page = (pageNum - 1) * pageSize;
List<Emp> empList = empMapper.selectByPage(page, pageSize);
PageInfo<Emp> pageInfo = new PageInfo<>(empList);
pageInfo.setTotal(empMapper.selectCount());
return R.ok(pageInfo);
}
}
@Mapper
public class EmpMapper{
List<Emp> selectByPage(@Param("page") Integer pageNum,
@Param("size") Integer pageSize);
Integer selectCount();
}
SQL
<!--返回前端的分頁信息 這里的數(shù)據(jù)表字段名有點不規(guī)范-->
<select id="selectByPage" resultType="Emp">
SELECT
id,name,sex,idcard,phonenum,depart
FROM
emp
LIMIT
#{page},#{size}
</select>
<!--返回前端的總記錄條數(shù)-->
<select id="selectCount" resultType="java.lang.Integer">
SELECT
count(*)
FROM
emp
</select>
測試返回數(shù)據(jù)
??????? 返回的分頁信息是在data中的list
MyBatis-Plus
引入依賴
<!--整合MyBatis
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.3</version>
</dependency>
-->
<!--
這里需要注意哈:如果使用了MyBatis-Plus的話就不能引入MyBatis依賴 否則會報錯
可能也不是因為兩個不能互存 只是版本之間產生了依賴 報錯原因如下圖所示
-->
<!--數(shù)據(jù)源配置-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
<!--MyBatis-Plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<!--JDBC-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
修改yml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/table?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
mybatis-plus:
mapper-locations: classpath:mapper/*.xml # 對應xml的位置
type-aliases-package: com.chf.entity # 對應namespace的實體類包名
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 日志類型
map-underscore-to-camel-case: true # 字段與屬性的駝峰規(guī)則
業(yè)務代碼
@RestController
@RequestMapping("/emp")
public class EmpController{
@Autowired
private EmpService empService;
/**
* 分頁查詢
* @param pageNum 當前頁數(shù)
* @param pageSize 每頁條數(shù)
* @return
*/
@GetMapping("/findAll/{page}/{size}")
public R findAll(@PathVariable("page") Integer pageNum, @PathVariable("size") Integer pageSize){
Page<Emp> page = new Page<>(pageNum, pageSize);
// 此方法還可以傳入第二個參數(shù):QueryWrapper條件構造器
// 用于增添一些查詢條件用的 這里就不做展示了
empService.page(page);
// 如果是調用數(shù)據(jù)訪問層的就是selectPage()方法即以下語句
// mapper.selectPage(page, QueryWrapper);
return R.ok(page);
}
}
public interface EmpService extends IService<Emp> {
}
@Service
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {
}
@Mapper
public interface EmpMapper extends BaseMapper<Emp> {
}
測試返回數(shù)據(jù)
??????? 可以看到在MyBatis-Plus返回前端的參數(shù)中使用records封裝分頁信息??吹竭@里以為結束了嗎?仔細看total(總條數(shù))會發(fā)現(xiàn)怎么會是0?還有pages(總頁數(shù))也是0,學過MyBatis-Plus應該都知道為了完成分頁所以還需要配置分頁插件才可以實現(xiàn)真正的分頁。所以需要再添加一個配置類,代碼如下:
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
???????? 添加好分頁插件再次查詢接口就會看到總條數(shù)和總頁數(shù)都是真實的數(shù)值了。
PageHelper
??????? 其實MyBatis底層就是調用Github的PageHelper插件工具。但是如果直接使用Github的分頁的話會更加簡便,但是有一個坑。只需要將上面MyBatis的業(yè)務代碼改為以下代碼塊。相比而言,代碼行數(shù)一致。多了一句PageMethod.startPage()、少了一句設置總條數(shù)的語句。
業(yè)務代碼
@RestController
@RequestMapping("/emp")
public class EmpController{
//@Autowired
//private EmpService empService;
// 為了博客簡化代碼量 所以直接調用Dao層接口
@Autowired
private EmpMapper empMapper;
/**
* 分頁查詢
* @param pageNum 當前頁數(shù)
* @param pageSize 每頁條數(shù)
* @return
*/
@GetMapping("/findAll/{page}/{size}")
public R findAll(@PathVariable("page") Integer pageNum, @PathVariable("size") Integer pageSize){
// 由于PageHelper繼承PageMethod但未重寫方法 所以寫成下面的語句
Page<Object> page = PageMethod.startPage(pageNum, pageSize);
// 獲取查詢出的列表
List<Emp> empList = empMapper.selectByPage(page, pageSize);
PageInfo<Emp> pageInfo = new PageInfo<>(empList);
// pageInfo.setTotal(empMapper.selectCount());
// 此時page已經有列表信息、與總條數(shù)了 無需再一條SQL查詢總條數(shù)
return R.ok(page);
}
}
?
踩坑
??????? 這里的踩坑處就是Page對象一定要在想要查詢的列表前先初始出來,否則過濾無效。這樣子Paga中的列表信息才是我們想要的查詢出來的信息。比如說:業(yè)務中我需要查詢A、B列表進行拼接啥的。主要是為了返回A列表的數(shù)據(jù),所以只有以下兩種組合方式(大于號表示業(yè)務代碼中靠前出現(xiàn)):
??????? Page > AList > BList。BList > Page > AList。文章來源:http://www.zghlxwxcb.cn/news/detail-769017.html
??????? 關于這個問題。我很好奇的追入源碼中閱讀。在PageMethod的startPage()中對Page對象進行設置。并且多了一步判斷當前線程(ThreadLocal)是否存在Page對象。不存在則創(chuàng)建,存在則直接分頁。至于源碼追蹤請參考這篇文章:Mybatis第三方PageHelper插件分頁原理-騰訊云開發(fā)者社區(qū)-騰訊云文章來源地址http://www.zghlxwxcb.cn/news/detail-769017.html
public abstract class PageMethod {
protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal();
public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
Page<E> page = new Page(pageNum, pageSize, count);
page.setReasonable(reasonable);
page.setPageSizeZero(pageSizeZero);
// 判斷當前線程中是否存在Page對象(執(zhí)行排序Order by之后)
Page<E> oldPage = getLocalPage(); // (Page)LOCAL_PAGE.get()
if (oldPage != null && oldPage.isOrderByOnly()) {
page.setOrderBy(oldPage.getOrderBy());
}
setLocalPage(page); // LOCAL_PAGE.set(page);
return page;
}
}
到了這里,關于【SpringBoot】MyBatis與MyBatis-Plus分頁查詢 & github中的PageHelper的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!