集成mybatis-plus

## 集成mybatis-plus实现mybatis增强 Mybatis-Plus是在Mybatis的基础上进行扩展,只做增强不做改变,可以兼容Mybatis原生的特性。同时支持通用CRUD操作、多种主键策略、分页、性能分析、全局拦截等。极大帮助我们简化开发工作。 1、ruoyi-common\pom.xml模块添加整合依赖 ```xml <!-- mybatis-plus 增强CRUD --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> ``` 2、ruoyi-admin文件application.yml,修改mybatis配置为mybatis-plus ``` # MyBatis Plus配置 mybatis-plus: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml ``` 3、添加Mybatis Plus配置MybatisPlusConfig.java。 PS:原来的MyBatisConfig.java需要删除掉 ```java package com.ruoyi.framework.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * Mybatis Plus 配置 * * @author ruoyi */ @EnableTransactionManagement(proxyTargetClass = true) @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 分页插件 interceptor.addInnerInterceptor(paginationInnerInterceptor()); // 乐观锁插件 interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor()); // 阻断插件 interceptor.addInnerInterceptor(blockAttackInnerInterceptor()); return interceptor; } /** * 分页插件,自动识别数据库类型 https://baomidou.com/guide/interceptor-pagination.html */ public PaginationInnerInterceptor paginationInnerInterceptor() { PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); // 设置数据库类型为mysql paginationInnerInterceptor.setDbType(DbType.MYSQL); // 设置最大单页限制数量,默认 500 条,-1 不受限制 paginationInnerInterceptor.setMaxLimit(-1L); return paginationInnerInterceptor; } /** * 乐观锁插件 https://baomidou.com/guide/interceptor-optimistic-locker.html */ public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() { return new OptimisticLockerInnerInterceptor(); } /** * 如果是对全表的删除或更新操作,就会终止该操作 https://baomidou.com/guide/interceptor-block-attack.html */ public BlockAttackInnerInterceptor blockAttackInnerInterceptor() { return new BlockAttackInnerInterceptor(); } } ``` 4、添加测试表和菜单信息 ```sql drop table if exists sys_student; create table sys_student ( student_id int(11) auto_increment comment '编号', student_name varchar(30) default '' comment '学生名称', student_age int(3) default null comment '年龄', student_hobby varchar(30) default '' comment '爱好(0代码 1音乐 2电影)', student_sex char(1) default '0' comment '性别(0男 1女 2未知)', student_status char(1) default '0' comment '状态(0正常 1停用)', student_birthday datetime comment '生日', primary key (student_id) ) engine=innodb auto_increment=1 comment = '学生信息表'; -- 菜单 sql insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark) values('学生信息', '3', '1', '/system/student', 'c', '0', 'system:student:view', '#', 'admin', sysdate(), '', null, '学生信息菜单'); -- 按钮父菜单id select @parentid := last_insert_id(); -- 按钮 sql insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark) values('学生信息查询', @parentid, '1', '#', 'f', '0', 'system:student:list', '#', 'admin', sysdate(), '', null, ''); insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark) values('学生信息新增', @parentid, '2', '#', 'f', '0', 'system:student:add', '#', 'admin', sysdate(), '', null, ''); insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark) values('学生信息修改', @parentid, '3', '#', 'f', '0', 'system:student:edit', '#', 'admin', sysdate(), '', null, ''); insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark) values('学生信息删除', @parentid, '4', '#', 'f', '0', 'system:student:remove', '#', 'admin', sysdate(), '', null, ''); insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark) values('学生信息导出', @parentid, '5', '#', 'f', '0', 'system:student:export', '#', 'admin', sysdate(), '', null, ''); ``` 5、新增测试代码验证 新增 ruoyi-system\com\ruoyi\system\controller\SysStudentController.java ```java package com.ruoyi.system.controller; import java.util.Arrays; import java.util.List; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.system.domain.SysStudent; import com.ruoyi.system.service.ISysStudentService; /** * 学生信息Controller * * @author ruoyi */ @Controller @RequestMapping("/system/student") public class SysStudentController extends BaseController { private String prefix = "system/student"; @Autowired private ISysStudentService sysStudentService; @RequiresPermissions("system:student:view") @GetMapping() public String student() { return prefix + "/student"; } /** * 查询学生信息列表 */ @RequiresPermissions("system:student:list") @PostMapping("/list") @ResponseBody public TableDataInfo list(SysStudent sysStudent) { startPage(); List<SysStudent> list = sysStudentService.queryList(sysStudent); return getDataTable(list); } /** * 导出学生信息列表 */ @RequiresPermissions("system:student:export") @Log(title = "学生信息", businessType = BusinessType.EXPORT) @PostMapping("/export") @ResponseBody public AjaxResult export(SysStudent sysStudent) { List<SysStudent> list = sysStudentService.queryList(sysStudent); ExcelUtil<SysStudent> util = new ExcelUtil<SysStudent>(SysStudent.class); return util.exportExcel(list, "student"); } /** * 新增学生信息 */ @GetMapping("/add") public String add() { return prefix + "/add"; } /** * 新增保存学生信息 */ @RequiresPermissions("system:student:add") @Log(title = "学生信息", businessType = BusinessType.INSERT) @PostMapping("/add") @ResponseBody public AjaxResult addSave(SysStudent sysStudent) { return toAjax(sysStudentService.save(sysStudent)); } /** * 修改学生信息 */ @GetMapping("/edit/{studentId}") public String edit(@PathVariable("studentId") Long studentId, ModelMap mmap) { SysStudent sysStudent = sysStudentService.getById(studentId); mmap.put("sysStudent", sysStudent); return prefix + "/edit"; } /** * 修改保存学生信息 */ @RequiresPermissions("system:student:edit") @Log(title = "学生信息", businessType = BusinessType.UPDATE) @PostMapping("/edit") @ResponseBody public AjaxResult editSave(SysStudent sysStudent) { return toAjax(sysStudentService.updateById(sysStudent)); } /** * 删除学生信息 */ @RequiresPermissions("system:student:remove") @Log(title = "学生信息", businessType = BusinessType.DELETE) @PostMapping("/remove") @ResponseBody public AjaxResult remove(String ids) { return toAjax(sysStudentService.removeByIds(Arrays.asList(ids))); } } ``` 新增 ruoyi-system\com\ruoyi\system\domain\SysStudent.java ```java package com.ruoyi.system.domain; import java.io.Serializable; import java.util.Date; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.common.annotation.Excel; /** * 学生信息对象 sys_student * * @author ruoyi */ @TableName(value = "sys_student") public class SysStudent implements Serializable { @TableField(exist = false) private static final long serialVersionUID = 1L; /** 编号 */ @TableId(type = IdType.AUTO) private Long studentId; /** 学生名称 */ @Excel(name = "学生名称") private String studentName; /** 年龄 */ @Excel(name = "年龄") private Integer studentAge; /** 爱好(0代码 1音乐 2电影) */ @Excel(name = "爱好", readConverterExp = "0=代码,1=音乐,2=电影") private String studentHobby; /** 性别(0男 1女 2未知) */ @Excel(name = "性别", readConverterExp = "0=男,1=女,2=未知") private String studentSex; /** 状态(0正常 1停用) */ @Excel(name = "状态", readConverterExp = "0=正常,1=停用") private String studentStatus; /** 生日 */ @JsonFormat(pattern = "yyyy-MM-dd") @Excel(name = "生日", width = 30, dateFormat = "yyyy-MM-dd") private Date studentBirthday; public void setStudentId(Long studentId) { this.studentId = studentId; } public Long getStudentId() { return studentId; } public void setStudentName(String studentName) { this.studentName = studentName; } public String getStudentName() { return studentName; } public void setStudentAge(Integer studentAge) { this.studentAge = studentAge; } public Integer getStudentAge() { return studentAge; } public void setStudentHobby(String studentHobby) { this.studentHobby = studentHobby; } public String getStudentHobby() { return studentHobby; } public void setStudentSex(String studentSex) { this.studentSex = studentSex; } public String getStudentSex() { return studentSex; } public void setStudentStatus(String studentStatus) { this.studentStatus = studentStatus; } public String getStudentStatus() { return studentStatus; } public void setStudentBirthday(Date studentBirthday) { this.studentBirthday = studentBirthday; } public Date getStudentBirthday() { return studentBirthday; } @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) .append("studentId", getStudentId()) .append("studentName", getStudentName()) .append("studentAge", getStudentAge()) .append("studentHobby", getStudentHobby()) .append("studentSex", getStudentSex()) .append("studentStatus", getStudentStatus()) .append("studentBirthday", getStudentBirthday()) .toString(); } } ``` 新增 ruoyi-system\com\ruoyi\system\mapper\SysStudentMapper.java ```java package com.ruoyi.system.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.system.domain.SysStudent; /** * 学生信息Mapper接口 * * @author ruoyi */ public interface SysStudentMapper extends BaseMapper<SysStudent> { } ``` 新增 ruoyi-system\com\ruoyi\system\service\ISysStudentService.java ```java package com.ruoyi.system.service; import java.util.List; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.system.domain.SysStudent; /** * 学生信息Service接口 * * @author ruoyi */ public interface ISysStudentService extends IService<SysStudent> { /** * 查询学生信息列表 * * @param sysStudent 学生信息 * @return 学生信息集合 */ public List<SysStudent> queryList(SysStudent sysStudent); } ``` 新增 ruoyi-system\com\ruoyi\system\service\impl\SysStudentServiceImpl.java ```java package com.ruoyi.system.service.impl; import java.util.List; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.domain.SysStudent; import com.ruoyi.system.mapper.SysStudentMapper; import com.ruoyi.system.service.ISysStudentService; /** * 学生信息Service业务层处理 * * @author ruoyi */ @Service public class SysStudentServiceImpl extends ServiceImpl<SysStudentMapper, SysStudent> implements ISysStudentService { @Override public List<SysStudent> queryList(SysStudent sysStudent) { // 注意:mybatis-plus lambda 模式不支持 eclipse 的编译器 // LambdaQueryWrapper<SysStudent> queryWrapper = Wrappers.lambdaQuery(); // queryWrapper.eq(SysStudent::getStudentName, sysStudent.getStudentName()); QueryWrapper<SysStudent> queryWrapper = Wrappers.query(); if (StringUtils.isNotEmpty(sysStudent.getStudentName())) { queryWrapper.eq("student_name", sysStudent.getStudentName()); } if (StringUtils.isNotNull(sysStudent.getStudentAge())) { queryWrapper.eq("student_age", sysStudent.getStudentAge()); } if (StringUtils.isNotEmpty(sysStudent.getStudentHobby())) { queryWrapper.eq("student_hobby", sysStudent.getStudentHobby()); } return this.list(queryWrapper); } } ``` 新增 ruoyi-system\templates\system\student\add.html ```html <!DOCTYPE html> <html lang="zh" xmlns:th="http://www.thymeleaf.org" > <head> <th:block th:include="include :: header('新增学生信息')" /> <th:block th:include="include :: datetimepicker-css" /> </head> <body class="white-bg"> <div class="wrapper wrapper-content animated fadeInRight ibox-content"> <form class="form-horizontal m" id="form-student-add"> <div class="form-group"> <label class="col-sm-3 control-label">学生名称:</label> <div class="col-sm-8"> <input name="studentName" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">年龄:</label> <div class="col-sm-8"> <input name="studentAge" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">爱好:</label> <div class="col-sm-8"> <input name="studentHobby" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">性别:</label> <div class="col-sm-8"> <select name="studentSex" class="form-control m-b"> <option value="">所有</option> </select> <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">状态:</label> <div class="col-sm-8"> <div class="radio-box"> <input type="radio" name="studentStatus" value=""> <label th:for="studentStatus" th:text="未知"></label> </div> <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">生日:</label> <div class="col-sm-8"> <div class="input-group date"> <input name="studentBirthday" class="form-control" placeholder="yyyy-MM-dd" type="text"> <span class="input-group-addon"><i class="fa fa-calendar"></i></span> </div> </div> </div> </form> </div> <th:block th:include="include :: footer" /> <th:block th:include="include :: datetimepicker-js" /> <script th:inline="javascript"> var prefix = ctx + "system/student" $("#form-student-add").validate({ focusCleanup: true }); function submitHandler() { if ($.validate.form()) { $.operate.save(prefix + "/add", $('#form-student-add').serialize()); } } $("input[name='studentBirthday']").datetimepicker({ format: "yyyy-mm-dd", minView: "month", autoclose: true }); </script> </body> </html> ``` 新增 ruoyi-system\templates\system\student\edit.html ```html <!DOCTYPE html> <html lang="zh" xmlns:th="http://www.thymeleaf.org" > <head> <th:block th:include="include :: header('修改学生信息')" /> <th:block th:include="include :: datetimepicker-css" /> </head> <body class="white-bg"> <div class="wrapper wrapper-content animated fadeInRight ibox-content"> <form class="form-horizontal m" id="form-student-edit" th:object="${sysStudent}"> <input name="studentId" th:field="*{studentId}" type="hidden"> <div class="form-group"> <label class="col-sm-3 control-label">学生名称:</label> <div class="col-sm-8"> <input name="studentName" th:field="*{studentName}" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">年龄:</label> <div class="col-sm-8"> <input name="studentAge" th:field="*{studentAge}" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">爱好:</label> <div class="col-sm-8"> <input name="studentHobby" th:field="*{studentHobby}" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">性别:</label> <div class="col-sm-8"> <select name="studentSex" class="form-control m-b"> <option value="">所有</option> </select> <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">状态:</label> <div class="col-sm-8"> <div class="radio-box"> <input type="radio" name="studentStatus" value=""> <label th:for="studentStatus" th:text="未知"></label> </div> <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">生日:</label> <div class="col-sm-8"> <div class="input-group date"> <input name="studentBirthday" th:value="${#dates.format(sysStudent.studentBirthday, 'yyyy-MM-dd')}" class="form-control" placeholder="yyyy-MM-dd" type="text"> <span class="input-group-addon"><i class="fa fa-calendar"></i></span> </div> </div> </div> </form> </div> <th:block th:include="include :: footer" /> <th:block th:include="include :: datetimepicker-js" /> <script th:inline="javascript"> var prefix = ctx + "system/student"; $("#form-student-edit").validate({ focusCleanup: true }); function submitHandler() { if ($.validate.form()) { $.operate.save(prefix + "/edit", $('#form-student-edit').serialize()); } } $("input[name='studentBirthday']").datetimepicker({ format: "yyyy-mm-dd", minView: "month", autoclose: true }); </script> </body> </html> ``` 新增 ruoyi-system\templates\system\student\student.html ```html <!DOCTYPE html> <html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"> <head> <th:block th:include="include :: header('学生信息列表')" /> </head> <body class="gray-bg"> <div class="container-div"> <div class="row"> <div class="col-sm-12 search-collapse"> <form id="formId"> <div class="select-list"> <ul> <li> <label>学生名称:</label> <input type="text" name="studentName"/> </li> <li> <label>年龄:</label> <input type="text" name="studentAge"/> </li> <li> <label>爱好:</label> <input type="text" name="studentHobby"/> </li> <li> <label>性别:</label> <select name="studentSex"> <option value="">所有</option> <option value="-1">代码生成请选择字典属性</option> </select> </li> <li> <label>状态:</label> <select name="studentStatus"> <option value="">所有</option> <option value="-1">代码生成请选择字典属性</option> </select> </li> <li> <label>生日:</label> <input type="text" class="time-input" placeholder="请选择生日" name="studentBirthday"/> </li> <li> <a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a> <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a> </li> </ul> </div> </form> </div> <div class="btn-group-sm" id="toolbar" role="group"> <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:student:add"> <i class="fa fa-plus"></i> 添加 </a> <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="system:student:edit"> <i class="fa fa-edit"></i> 修改 </a> <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:student:remove"> <i class="fa fa-remove"></i> 删除 </a> <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:student:export"> <i class="fa fa-download"></i> 导出 </a> </div> <div class="col-sm-12 select-table table-striped"> <table id="bootstrap-table"></table> </div> </div> </div> <th:block th:include="include :: footer" /> <script th:inline="javascript"> var editFlag = [[${@permission.hasPermi('system:student:edit')}]]; var removeFlag = [[${@permission.hasPermi('system:student:remove')}]]; var prefix = ctx + "system/student"; $(function() { var options = { url: prefix + "/list", createUrl: prefix + "/add", updateUrl: prefix + "/edit/{id}", removeUrl: prefix + "/remove", exportUrl: prefix + "/export", modalName: "学生信息", columns: [{ checkbox: true }, { field: 'studentId', title: '编号', visible: false }, { field: 'studentName', title: '学生名称' }, { field: 'studentAge', title: '年龄' }, { field: 'studentHobby', title: '爱好' }, { field: 'studentSex', title: '性别' }, { field: 'studentStatus', title: '状态' }, { field: 'studentBirthday', title: '生日' }, { title: '操作', align: 'center', formatter: function(value, row, index) { var actions = []; actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.studentId + '\')"><i class="fa fa-edit"></i>编辑</a> '); actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.studentId + '\')"><i class="fa fa-remove"></i>删除</a>'); return actions.join(''); } }] }; $.table.init(options); }); </script> </body> </html> ``` 6、登录系统测试学生菜单增删改查功能。 > 提示 > 下载相关代码实现示例 ruoyi/集成mybatisplus实现mybatis增强.zip