Mybatis Plus 精华教程

引言

        Mybatis Plus 是继承了Java的精髓:MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。(引用官方原话)

        在这里我想说几句题外话:

1.推荐跳过Mybatis ,直接学MybatisPlus

2.要掌握最好熟练使用SQL

3.本文尽提取常用的一些知识点,这个远远没有官方资料更详尽!所以遇到问题多去官网查文档(文档是中文的,不用担心)。

4.Mybatis Plus 只是简化操作,不代表它是万能的,所以复杂的业务仍然需要通过Mybatis 中写XML实现。

5.针对业务,如增、删、改 都是有逻辑的,所以需要对其方法进行重构,但简单查询则不需要,所以说MybatisPlus可以减少我们15%的工作量,再多了就夸张了!

6.注意我用的MybatisPlus版本,另外,开发环境我使用的是Mac

筹备

数据库:mysql 8.0.27

                表:

                学校表 

DROP TABLE IF EXISTS `school`;
CREATE TABLE `school` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL COMMENT '名称',
  `rem` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '描述',
  `status` tinyint DEFAULT '0' COMMENT '状态。0:正常;1:禁用',
  `creater` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `create_id` int DEFAULT NULL COMMENT '创建人ID',
  `modifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '修改人',
  `modifier_id` int DEFAULT NULL COMMENT '修改人ID',
  `modifier_time` datetime DEFAULT NULL COMMENT '修改时间',
  `is_delete` int DEFAULT '0' COMMENT '删除标识',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

SET FOREIGN_KEY_CHECKS = 1;

                学生表

DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` int NOT NULL AUTO_INCREMENT,
  `school_id` int DEFAULT NULL COMMENT '学校ID',
  `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  `age` int DEFAULT NULL COMMENT '年龄',
  `rem` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '描述',
  `status` tinyint DEFAULT '0' COMMENT '状态。0:正常;1:禁用',
  `creater` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `create_id` int DEFAULT NULL COMMENT '创建人ID',
  `modifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '修改人',
  `modifier_id` int DEFAULT NULL COMMENT '修改人ID',
  `modifier_time` datetime DEFAULT NULL COMMENT '修改时间',
  `is_delete` int DEFAULT '0' COMMENT '删除标识',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

SET FOREIGN_KEY_CHECKS = 1;

配置注意项目

数据库连接时如果连接不成功,会提示serverTimezone 找不到,原因是时区可能不被识别,把相关时区去除就可以了,如下:
&serverTimezone=CTT    

maven配置

       <!-- mysql 驱动 -->
       <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>8.0.27</scope>
        </dependency>
        <!-- lombok 插件 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- druid 连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>
        <!-- mybatis-plus 目前是最新版 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

配置连接

#Spring 连接配置
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://127.0.1:3306/MybatisPlusTest?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&allowMultiQueries=true
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
# 端口配置
server:
  port: 10086

一、使用Mybatis Plus 先起步(开胃小菜)

     目标   :对学校表实现增、删、改、查

1.1 创建一个Spring boot web项目

        这里忽略了,不会的请看我之前的教程 (点这里

1.2 配置相关类与实现

        

package com.example.mydemo.po;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;

import java.sql.Date;

@Data
@TableName("school")
public class School {
    @TableId(type = IdType.AUTO) //标记自增长
    private Integer id;

    @TableField("name")
    private String name;

    @TableField("rem")
    private String rem;

    @TableField("status")
    private  Integer status;

    @TableField("creater")
    private String creater;

    @TableField("create_time") //定义数据库字段
    private Date createTime;

    @TableField("create_id")//定义数据库字段
    private Integer createId;

    @TableField("modifier")
    private String modifier;

    @TableField("modifier_id")//定义数据库字段
    private Integer modifierId;

    @TableField("modifier_time")//定义数据库字段
    private Date modifierTime;

    @TableField("is_delete")
    private Integer isDelete;
}

1.3 定义Mapper接口

package com.example.mydemo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mydemo.po.School;

public interface SchoolDao extends BaseMapper<School> {
}

1.4 测试

1.新增

@SpringBootTest
class MydemoApplicationTests {
    @Autowired
    private SchoolDao schoolDao;

    @Test
    void contextLoads() {
        System.out.println("----------------");
        //新增
        schoolDao.insert(new School(){{setName("上海大学");}});
        //List<School> schools=schoolDao.selectList(null);
        //System.out.println(schools);
    }
}

2.修改

schoolDao.updateById(new School(){{setId(1);setName("苏州大学");}});

3.查询 

List<School> schools=schoolDao.selectList(null);
System.out.println(schools);

4.删除

schoolDao.deleteById(new School(){{setId(1);}});

1.5 显示具体SQL执行语句配置

配置 application.yml

#Spring 连接配置
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://127.0.1:3306/MybatisPlusTest?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&allowMultiQueries=true
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
# 端口配置
server:
  port: 10086
# SQL 日志显示
logging:
  level:
    root: info
    com.example.mydemo: debug

效果:

二、聊一聊常见的注解 (核心)

操作注解说明示例
类、表 对应@TableName("数据库表名")对实体类注解到数据库表上
@TableName("school")
public class School {
......
}
对应数据库中的字段配置@TableId(IdType.AUTO)设置类元素对应字段自增长
@TableId(type = IdType.AUTO) //标记自增长
private Integer id;
@TableField("对应数据库字段")设置类元素对应字段对应数据库字段
@TableField("create_time") //定义数据库字段
private Date createTime;
@TableField(exist=false)设置元素不为数据库字段(默认为true)
@TableField(fill = FieldFill.数据库操作) 
数据库操作自动填充(需要再写一个自动填充实现类)
@TableField(value = "create_time",fill = FieldFill.INSERT) //定义数据库字段
private Date createTime;
@Version定义字段为版本(注意此处为int类型)
@TableLogic逻辑字段,用于假删除

示例 自动填充 & 逻辑删除(假删除)

1.创建自动填充类

package com.example.mydemo.complete;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "modifierTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
    }
}

2.定义实体类

*  注意我定义的日期类型

package com.example.mydemo.po;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;

import java.sql.Date;
import java.time.LocalDateTime;

@Data
@TableName("school")
public class School {
    @TableId(type = IdType.AUTO) //标记自增长
    private Integer id;

    @TableField("name")
    private String name;

    @TableField("rem")
    private String rem;

    @TableField("status")
    private  Integer status;

    @TableField("creater")
    private String creater;

    @TableField(value = "create_time",fill = FieldFill.INSERT) //定义数据库字段
    private LocalDateTime createTime;

    @TableField("create_id")//定义数据库字段
    private Integer createId;

    @TableField("modifier")
    private String modifier;

    @TableField("modifier_id")//定义数据库字段
    private Integer modifierId;

    @TableField(value = "modifier_time",fill = FieldFill.UPDATE) //定义数据库字段
    private LocalDateTime modifierTime;

    @TableField("is_delete")
    @TableLogic
    private Integer isDelete;
}

3.测试

schoolDao.insert(new School(){{setName("山东大学");}});

schoolDao.updateById(new School(){{setId(9);setName("大学");}});

 

schoolDao.deleteById(new School(){{setId(9);}});

三、CRUD (更上一层楼)

如上例所示,并不是所有的仅使用Mapper实际业务是不符合Spring 开发思想的,所以我们还要建立service 层及Impl 实现层

service

package com.example.mydemo.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.mydemo.po.School;

/**
 * 接口 继承 Iservice<T> 来实现内部通用接口
 */
public interface SchoolService extends IService<School> {
}

impl

/**
 * 1.继承通用实现
 * 2.实现接口进行挂靠
 * 3.注意交给Service 注册
 */
@Service("schoolService")
public class SchoolServiceImpl extends ServiceImpl<SchoolDao, School> implements SchoolService {
}

常用接口(增、删、改、查)

boolean save(T entity);单增
boolean saveBatch(Collection<T> entityList);批增
boolean update(T updateEntity, Wrapper<T> whereWrapper);根据 whereWrapper 条件,更新记录
boolean updateById(T entity);根据 ID 选择修改
boolean updateBatchById(Collection<T> entityList);根据ID 批量更新
boolean update(Wrapper<T> updateWrapper);根据 UpdateWrapper 条件,更新记录 需要设置sqlset
增/改boolean saveOrUpdate(T entity);注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdateBatch(Collection<T> entityList);批量修改插入
boolean remove(Wrapper<T> queryWrapper);根据 entity 条件,删除记录
boolean removeById(Serializable id);根据 ID 删除
boolean removeByMap(Map<String, Object> columnMap);根据 columnMap 条件,删除记录
  T getById(Serializable id);根据 ID 查询
T getOne(Wrapper<T> queryWrapper);根据 Wrapper,查询一条记录
List<T> list();全部
List<T> list(Wrapper<T> queryWrapper);查询列表

四、条件构造器(万能钥匙)

QueryWrapper 与 UpdateWarpper这个对象通常作为载体实现条件构造

条件SQL
allEq()==
eq()=
ne<>
gt>
ge>=
lt<
le<=
betweenbetween
notBetweennot between
likelike
notLikenot like
likeLeftlike '%s'
likeRightlike 's%'
isNullis null
inin
notInnot in
inSqlin (sql...)
groupBygroup by
orderByAscorder  by asc
orderByDescorder  by desc
orderByorder by
havinghaving
funcfunc(函数)
or or 
and and

示例

@Test
    void contextLoads() {
        System.out.println("------查询示例----------");
        List<Integer> list=new ArrayList<>();
        list.add(2);
        list.add(3);
        list.add(4);
        QueryWrapper<School> queryWrapper=new QueryWrapper<>();
        
        //如下操作翻译为:select * from school where id in(2,3,4) and name='苏州大学'
        queryWrapper.in("id",list).eq("name","苏州大学");
        List<School> schools1=schoolService.list(queryWrapper);
        System.out.println(schools1);

        System.out.println("------更新示例----------");
        UpdateWrapper<School> updateWrapper=new UpdateWrapper<>();

        //如下操作翻译为:update school set name='随便测试' where id=2
        updateWrapper.eq("id",2).set("name","随便测试"); 
        schoolService.update(updateWrapper);
    }

五、常用到的插件(锦上添花)

5.1 分页

        5.1.1常见接口

接口描述
IPage<T> page(IPage<T> page);无条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);条件分页查询

        5.1.2 启用分页配置

        * 1.注意我的MybatisPlus版本,低版本不可以

            2.我的数据库是Mysql 所以在设置时注意选择使用:Dbtype.Mysql

package com.example.mydemo.complete;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("com.example.mydemo.mapper")
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

        5.1.3 测试效果

@Test
    void contextLoads() {
        System.out.println("------分页示例(按条件)----------");
        IPage<School> iPage =new Page<>(1,2);

        QueryWrapper<School>queryWrapper=new QueryWrapper<>();
        queryWrapper.like("name","浙江");

        iPage=schoolService.page(iPage,queryWrapper);
        List<School> schools=iPage.getRecords();
        System.out.println(schools);
        System.out.println(iPage.getPages());
    }

5.2 日志

5.2.1 maven

<!-- SQL 日志打印-->
<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>3.9.1</version>
</dependency>

5.2.2 合局配置

#Spring 连接配置
spring:
  datasource:
    username: root
    password: 123456
    #url: jdbc:mysql://127.0.1:3306/MybatisPlusTest?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&allowMultiQueries=true
    #driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:p6spy:mysql://127.0.1:3306/MybatisPlusTest?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&allowMultiQueries=true
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver
    type: com.alibaba.druid.pool.DruidDataSource
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

# 端口配置
server:
  port: 10086
# SQL 日志显示
logging:
  level:
    root: info
    com.example.mydemo: debug
mybatis-plus:
  global-config:
    db-config:
      id-type: auto

5.2.3 创建配置文件

spy.properties 

#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2

5.2.4 测试

 5.2.5 总结

其实如果有这个SQL语句就不需要自带的SQL 输出了,可以把原来的注释掉(这样可以提高运行速度)

六、代码自动生成器(甩手掌柜)

6.1 Maven依赖

<!-- 代码生成器 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.2</version>
</dependency>
<!-- 代码生成器模板引擎 -->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.3</version>
</dependency>
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
</dependency>
<!--  swagger可理解为接口文档规范      -->
<dependency>
    <groupId>io.swagger</groupId>
    <artifactId>swagger-annotations</artifactId>
    <version>1.6.2</version>
</dependency>

6.2 实现代码

package com.example.mydemo;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Column;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class CodeGenerator {


    public static void main(String[] args) {
        DataSourceConfig.Builder builder1 = new DataSourceConfig.
                Builder("jdbc:mysql://127.0.1:3306/MybatisPlusTest?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true",
                "root", "123456");
        FastAutoGenerator.create(builder1)
                .globalConfig((scanner, builder) -> builder.outputDir(System.getProperty("user.dir") + "/src/main/java")
                        .author(scanner.apply("作者名字"))
                        .enableSwagger()//开户swagger


                )
                .packageConfig((scanner, builder) -> builder.parent(scanner.apply("包名字")))
                .strategyConfig((scanner, builder) -> builder.addInclude(getTables(scanner.apply("表名字,多个用?分隔开?all")))
                        .controllerBuilder().enableRestStyle().enableHyphenStyle().serviceBuilder().formatServiceFileName("%sService")
                        .entityBuilder().enableLombok().enableTableFieldAnnotation().addTableFills(
                                new Column("create_time", FieldFill.INSERT)
                        ).build())
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();


    }

    protected static List<String> getTables(String tables) {
        return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
    }

}

6.4 效果

 

后记

MybatisPlus 能解决15%的工作量,别外的85%是需要Mybatis(自定义接口)来完成,即便如此,我们仍然要怀着一种感恩的心来看待它,不仅仅它是中国人自己写的,毕竟你少花了15%的时间就相当于创建价值。所以不要做键盘侠,多一些支持,在这里推荐大家关注 MybatisPlus官网

全文完,如觉得本文对您多少还有些帮助,麻烦您点赞支持一下!

原创不易,转载请注明出处

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值