MybatisPlus - [04] 分页
limit m,n
、PageHelper
、MyBatisPlus分页插件
001 || MybatisPlus分页插件
(1)引入maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.4</version>
</dependency>
(2)在MybatisPlusConfig中进行配置
package com.harley.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 MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor paginationInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 指定数据库类型
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加
// 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
return interceptor;
}
}
(3)测试
@Test
void testPage(){
Page<User> page = new Page<>(1, 5);
userMapper.selectPage(page, null);
page.getRecords().forEach(System.out::println);
}
(4)Service层
package com.harley.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.harley.entity.Account;
import java.util.List;
/**
* <p>
* 需要同步元数据的表配置 服务类
* </p>
*
* @author harley
* @since 2024-12-17
*/
public interface AccountService extends IService<Account> {
IPage<Account> getRecordPage(int currentPage, int pageSize, String keyword);
}
(5)实现类
package com.harley.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.harley.entity.Account;
import com.harley.mapper.AccountMapper;
import com.harley.service.AccountService;
/**
* <p>
* 需要同步元数据的表配置 服务实现类
* </p>
*
* @author harley
* @since 2024-12-17
*/
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements AccountService {
@Autowired
private AccountMapper accountMapper;
@Override
public IPage<Account> getRecordPage(int currentPage,int pageSize,String keyword){
// 创建Page对象, 传入当前页和每页记录数
Page<Account> page = new Page<>(currentPage, pageSize);
LambdaQueryWrapper<Account> lambdaQueryWrapper = new LambdaQueryWrapper<>();
// 根据更新时间降序排列
lambdaQueryWrapper.orderByDesc(Account::getUpdateTime);
// 如果关键字非空,则进行模糊查询
if( keyword != null && !keyword.isEmpty()){
lambdaQueryWrapper.like(Account::getName,keyword)
.or()
.like(Account::getUsername,keyword);
}
// 进行分页查询
return accountMapper.selectPage(page, lambdaQueryWrapper);
}
}
(6)Controller层
package com.harley.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.harley.entity.Account;
import com.harley.mapper.AccountMapper;
import com.harley.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
*
* @author harley
* @since 2024-12-17
*/
@RestController
@RequestMapping("/account")
public class SyncTblConfigController {
@Autowired
private AccountService accountService;
@GetMapping("/getRecordPage")
public IPage<Account> getRecordPage(@RequestParam Integer currentPage,
@RequestParam Integer pageSize,
@RequestParam(value = "keyword", defaultValue = "", required = false) String keyword){
return accountService.getRecordPage(currentPage, pageSize, keyword);
}
}
(7)vue页面
<template>
<div>
<div class="page-main">
<!-- 搜索框和按钮 -->
<div class="search-bar">
<el-input placeholder="请输入数据库名或表名关键字" v-model="query.keyword" style="width:500px;" clearable @input="debouncedFetchRecords">
<!-- <template #append>
<el-button type="primary" icon="el-icon-search" @click="fetchrecords">搜索</el-button>
</template> -->
</el-input>
<el-button type="success" style="margin-left:30px;" @click="showDialog('add',row=null)">新增</el-button>
</div>
</div>
<el-table :data="records" style="width: 100%">
<el-table-column prop="id" label="序号" width="auto"></el-table-column>
<el-table-column prop="databaseName" label="数据库" width="auto"></el-table-column>
<el-table-column prop="tableName" label="表名" width="400"></el-table-column>
<el-table-column prop="operator" label="操作人员">
<template slot-scope="scope">{{ scope.row.operator || 'N/A'}}</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间"></el-table-column>
<el-table-column prop="updateTime" label="更新时间"></el-table-column>
<el-table-column prop="owner" label="owner"></el-table-column>
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-button size="mini" type="primary" @click="showDialog('edit',scope.row)"><i class="el-icon-edit" style="font-size: 15px;"></i> 编辑</el-button>
<!-- <el-button size="mini" type="danger" @click="deleteRecord(scope.row.id)"><i class="el-icon-delete" style="font-size: 15px;"></i> 删除</el-button> -->
</template>
</el-table-column>
</el-table>
<!-- 分页控件 -->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="query.pageNum"
:page-size="query.pageSize"
:total="query.total"
layout="total, sizes, prev, pager, next, jumper"
:page-sizes="[5, 10]"
style="text-align: center;"
></el-pagination>
<!-- 新增/编辑对话框 -->
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="30%">
<el-form :model="form" :rules="rules" ref="form" label-width="100px">
<el-form-item label="编号" prop="id">
<el-input v-model="form.id" disabled></el-input>
</el-form-item>
<el-form-item label="数据库" prop="databaseName">
<el-input v-model="form.databaseName"></el-input>
</el-form-item>
<el-form-item label="表名" prop="tableName">
<el-input v-model.number="form.tableName"></el-input>
</el-form-item>
<el-form-item label="操作人员" prop="operator">
<el-input v-model.number="form.operator"></el-input>
</el-form-item>
<el-form-item label="owner" prop="owner">
<el-input v-model.number="form.owner"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button> <!-- 点击取消按钮,遮罩层隐藏 -->
<el-button type="primary" @click="handleSubmit">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import axios from 'axios';
import { debounce } from 'lodash';
export default {
name: 'SyncTblConfigPage',
data() {
return {
query: {
keyword: '',
pageNum: 0,
pageSize: 5,
total: 10,
},
tableData: [],
loading: false,
records: [],
editVDialogVisible: false,
selectedRecord: null,
dialogVisible: false, // 控制对话框的显示与隐藏,默认为隐藏
dialogTitle: '', // 对话框标题
form: {
id: null,
name: '',
username: '',
password: '',
comment: '',
},// 表单数据
rules: {
databaseName: [{ required: true, message: '数据库名不能为空', trigger: 'blur' }],
tableName: [{ required: true, message: '表名不能为空', trigger: 'blur' }],
operator: [{ required: false, message: '请输入操作人员', trigger: 'blur' }],
owner: [{ required: true, message: 'owner不能为空', trigger: 'blur' }],
}, // 表单验证规则
currentRow: null, // 当前编辑的行数据
};
},
created() {
this.fetchrecords();
this.debouncedFetchRecords = debounce(this.fetchrecords, 500);
this.$watch('query.keyword', (newVal) => {
if (!newVal) {
this.fetchrecords();
}else {
this.debouncedFetchRecords = debounce(this.fetchrecords, 500);
}
});
},
methods: {
async fetchrecords() {
await axios.get('/api/syncTblConfig/getRecordPage',{
params: {
currentPage: this.query.pageNum,
pageSize: this.query.pageSize,
keyword: this.query.keyword,
}
}).then(response => {
this.records = response.data.records.map(Record => ({
id: Record.id,
databaseName: Record.databaseName,
tableName: Record.tableName,
operator: Record.operator,
createTime: new Date(Record.createTime).toLocaleString(),
updateTime: new Date(Record.updateTime).toLocaleString(),
owner: Record.owner,
}));
this.query.total = response.data.total;
this.query.pageNum = response.data.current;
this.query.pageSize = response.data.size;
}).catch(error => {
console.error('There was an error fetching the records!', error);
});
},
showDialog(type, row = null) {
this.dialogVisible = true;
this.dialogTitle = type === 'add' ? '新增记录' : '编辑记录';
this.currentRow = row;
if (type === 'add') {
this.$refs.form && this.$refs.form.resetFields();
} else if (row) {
this.form = { ...row }; // 使用展开运算符复制对象以避免引用问题
}
},
async deleteRecord(id){
try{
const response = await axios.get(`/api/Record/del?id=${id}`);
console.log('已删除: ' + response.data)
await this.fetchrecords();
}catch(error){
console.error('删除失败', error);
}
},
handleSubmit() {
if (this.dialogTitle === '新增记录') {
this.$refs.form.validate((valid) => {
if (valid) {
axios.post('/api/Record/addRecord', this.form)
.then(response => {
console.log('新增成功: ' + response.data);
this.$message({
message: '新增账号',
type: 'success'
});
this.dialogVisible = false;
this.records.push({ ...this.form });
this.fetchrecords();
})
.catch(error => {
console.error('新增账号失败', error);
this.$message({
message: '新增账号失败',
type: 'error'
});
});
} else {
console.log('表单验证失败!!');
return false;
}
});
} else if(this.dialogTitle === '编辑记录'){
this.$refs.form.validate((valid) => {
if (valid) {
axios.put(`/api/Record/updateRecord/${this.form.id}`, this.form)
.then(response => {
console.log('更新成功: ' + response.data);
this.$message({
message: response.data,
type: 'success'
});
this.dialogVisible = false;
const index = this.records.findIndex(Record => Record.id === this.form.id);
if (index !== -1) {
this.$set(this.records,index, { ...this.form });
}
this.fetchrecords();
})
.catch(error => {
console.error('更新失败', error);
this.$message({
message: '更新失败',
type: 'error'
});
});
} else {
console.log('表单验证失败!!');
return false;
}
});
}
},
handleSizeChange(newSize) {
console.log(`每页 ${newSize} 条`);
this.query.pageSize = newSize;
this.fetchrecords();
},
handleCurrentChange(newPage) {
console.log(`当前页: ${newPage}`);
this.query.pageNum = newPage;
this.fetchrecords();
},
debouncedFetchRecords: debounce(function(){this.fetchRecords()}, 500).bind(this),
}
}
</script>
<style scoped>
</style>
— 业精于勤荒于嬉,行成于思毁于随 —
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南