#mybatis-plus
2.1 介绍mybatis-plus
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 但是对于联表操作还必须使用mybatis
#2.2 特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错 JDK1.
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
2.3练习crud
项目结构
2.4 如何使用
- 创建一个springboot工程并加入相关的依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yk</groupId>
<artifactId>mybatis-plus</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis-plus</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.13</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.配置文件和启动配置
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/shop?serverTimezone=Asia/Shanghai
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#配置映射文件所在的路径
mybatis.mapper-locations=classpath:/mapper/*.xml
spring.mvc.static-path-pattern=/static/**
server.port=8081
#日志打印
logging.level.com.yk.mybatisplus.mapper=debug
package com.yk.mybatisplus;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(basePackages = {"com.yk.mybatisplus.mapper"})
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class, args);
}
}
3.实体类
package com.yk.mybatisplus.entry;
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "tab_emp")
public class TabEmp {
@TableId(type = IdType.AUTO)
private Integer empId;
private String empName;
private String empSex;
private java.sql.Date empBirth;
private String empPhone;
private String empAddr;
private String empDist;
private java.sql.Date empHiredate;
@TableLogic
private Integer deleted;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
4.接口mapper
package com.yk.mybatisplus.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yk.mybatisplus.entry.TabEmp;
public interface EmpMapper extends BaseMapper<TabEmp> {
}
5.在主启动类上mapper的扫描
package com.yk.mybatisplus;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(basePackages = {"com.yk.mybatisplus.mapper"})
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class, args);
}
}
6.配置文件configuration
package com.yk.mybatisplus.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Date;
@Configuration
public class MybatisPlusConfig implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
}
//分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
7.service接口层
package com.yk.mybatisplus.service;
import com.yk.mybatisplus.entry.LayUIEntry;
import com.yk.mybatisplus.entry.ReturnData;
import com.yk.mybatisplus.entry.TabEmp;
public interface EmpService {
LayUIEntry selectEmp();
ReturnData insertEmp(TabEmp tabEmp);
ReturnData updateEmp(TabEmp tabEmp);
TabEmp selectEmpById(Integer empId);
ReturnData deleteEmp(Integer empId);
}
8.service类的实现层
package com.yk.mybatisplus.service;
import com.yk.mybatisplus.entry.LayUIEntry;
import com.yk.mybatisplus.entry.ReturnData;
import com.yk.mybatisplus.entry.TabEmp;
import com.yk.mybatisplus.mapper.EmpMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class EmpServiceImpl implements EmpService{
@Resource
private EmpMapper empMapper;
@Override
public LayUIEntry selectEmp() {
List<TabEmp> list=empMapper.selectList(null);
return new LayUIEntry(0,"success",list);
}
@Override
public ReturnData insertEmp(TabEmp tabEmp) {
int i=empMapper.insert(tabEmp);
if(i>0){
return new ReturnData(true,"success");
}else {
return new ReturnData(false,"success");
}
}
@Override
public ReturnData updateEmp(TabEmp tabEmp) {
int i=empMapper.updateById(tabEmp);
if(i>0){
return new ReturnData(true,"success");
}else {
return new ReturnData(false,"success");
}
}
@Override
public TabEmp selectEmpById(Integer empId) {
return empMapper.selectById(empId);
}
@Override
public ReturnData deleteEmp(Integer empId) {
int i=empMapper.deleteById(empId);
if(i>0){
return new ReturnData(true,"success");
}else {
return new ReturnData(false,"success");
}
}
}
9.前端页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title></title>
<script type="text/javascript" th:src="@{/static/layui/layui.js}"></script>
<link rel="stylesheet" type="text/css" th:href="@{/static/layui/css/layui.css}"/>
</head>
<body>
<table class="layui-hide" id="TestTable" lay-filter="test"></table>
<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="edit">修改</a>
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="delete">删除</a>
</script>
<script type="text/html" id="toolbarDemo">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-sm" lay-event="add">添加</button>
</div>
</script>
<div id="testDiv" style="display: none">
<form class="layui-form" action="" id="TestForm" lay-filter="example">
<div class="layui-form-item">
<label class="layui-form-label">姓名</label>
<div class="layui-input-block">
<input name="empId" id="id" lay-verify="id" autocomplete="off" placeholder="id" class="layui-input" style="display: none">
<input type="text" name="empName" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">性别</label>
<div class="layui-input-block">
<input type="text" name="empSex" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">手机号</label>
<div class="layui-input-block">
<input type="text" name="empPhone" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">地址</label>
<div class="layui-input-block">
<input type="text" name="empAddr" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">出生日期</label>
<div class="layui-input-block">
<input type="date" name="empBirth" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">邮编</label>
<div class="layui-input-block">
<input type="text" name="empDist" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">入职时间</label>
<div class="layui-input-block">
<input type="date" name="empHiredate" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="button" class="layui-btn" lay-submit="" lay-filter="saveBtn">保存</button>
<button type="reset" id="re" class="layui-btn" lay-filter="saveBtn">重置</button>
</div>
</div>
</form>
</div>
<script th:inline="none">
//加载模块(从layui 2.6 开始,第一个参数不传即代表加载所有内置模块)
layui.use(['layer', 'table','form'], function() {
var table = layui.table;
var form = layui.form;
var $ = layui.jquery;
function loadPage(){
//执行一个 table 实例
table.render({
elem: '#TestTable'
,height: 620
,url: '/ajax/selectEmp' //数据接口
,title: '员工管理'
,page: true //开启分页
,toolbar: "#toolbarDemo" //开启工具栏,此处显示默认图标,可以自定义模板,详见文档
,cols: [[
{field: 'empName', align: 'center', title: '员工姓名'}
, {
field: 'empSex', align: 'center', title: '性别', sort: true, templet: function (data) {
if (data.empSex == "男") {
return '男';
} else {
return '女';
}
}
}
, {field: 'empBirth', align: 'center', title: '出生日期', sort: true, hide: true}
, {field: 'empPhone', align: 'center', title: '手机号', sort: true}
, {field: 'empAddr', align: 'center', title: '地址', sort: true}
, {field: 'empDist', align: 'center', title: '邮编', sort: true}
, {field: 'empHiredate', align: 'center', title: '入职时间'}
, {fixed: 'right', width: 300, align: 'center', title: "操作", toolbar: '#barDemo'}
]]
,id:"loadMoney"
});
}
loadPage()
//监听头
table.on('toolbar(test)', function(obj){
if(obj.event=='add'){
$("#TestForm")[0].reset();//表单重置
layer.open({
title:"添加员工",
type: 1,
skin: 'layui-layer-demo', //样式类名
closeBtn: 1, //不显示关闭按钮
anim: 2,
area: ['620px', '440px'], //宽高
shadeClose: true, //开启遮罩关闭
content: $("#testDiv")
});
}
})
//监听行工具事件
table.on('tool(test)', function(obj){
console.log(obj)
console.log(obj.data.empId);
if(obj.event=='edit'){
$.ajax({
url:"/ajax/selectEmpById?empId="+obj.data.empId,
data:{},
dataType:"json",
type:"get",
success:function (reData){
//回显:
console.log(reData)
layer.open({
title:"修改员工信息",
type: 1,
skin: 'layui-layer-demo', //样式类名
closeBtn: 1, //不显示关闭按钮
anim: 2,
area: ['620px', '440px'], //宽高
shadeClose: true, //开启遮罩关闭
content: $("#testDiv")
});
form.val('example', reData);
}
})
}else if(obj.event=='delete'){
$.ajax({
url:"/ajax/deleteEmp?empId="+obj.data.empId,
data:{},
dataType:"json",
type:"delete",
success:function (reData){
layer.confirm('确认删除?', {
title:'提醒',
area:['240px','160px'], //弹框的大小
btn:['确认','取消'] //按钮
}, function(){
layer.closeAll('dialog');
layer.msg("删除成功")
loadPage();//加载查询列表
})
}
})
}
})
//监听提交
form.on('submit(saveBtn)', function(data){
var empId=$("#id").val();
if(empId!=null&&empId!=""){
$.ajax({
url:"/ajax/updateEmp",
data:JSON.stringify(data.field),
dataType:"json",
contentType:"application/json",
type:"post",
success:function (redata){
if(redata.state){
layer.closeAll();//关闭弹出框
loadPage();//加载查询列表
layer.msg(redata.message)
$("#TestForm")[0].reset();//表单重置
}else{
layer.msg(redata.message)
}
}
});
}else{
$.ajax({
url:"/ajax/insertEmp",
data:JSON.stringify(data.field),
dataType:"json",
contentType:"application/json",
type:"post",
success:function (redata){
if(redata.state){
layer.msg(redata.message)
loadPage();//加载查询列表
layer.closeAll();//关闭弹出框
$("#TestForm")[0].reset();//表单重置
}else{
layer.msg(redata.message)
location.reload()
}
}
});
}
});
});
</script>
</body>
</html>
测试结果
查询
新增修改
删除
说明:
只对自动注入的sql起效:
插入: 不作限制
查找: 追加where条件过滤掉已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段
更新: 追加where条件防止更新到已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段
删除: 转变为 更新
mybatis-plus简化了单表的增删改查的操作,大大提高了效率