栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

2022/5/30 Mybatis-Plus详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

2022/5/30 Mybatis-Plus详解

目录

1.Mybatis-Plus简介

2.特性 

3.支持数据库

4.框架结构

5.快速开始 

        5.1 创建数据库mybatis_plus

        5.2 搭建项目

                5.2.1 创建Spring Boot工程

                5.2.2 导入依赖

                5.2.3 配置yml 

                5.2.4 entity实体类

                5.2.5 mapper 

                5.2.6 service 

                5.2.7  service实现类

6.使用Mybatis-Plus简化CURD 

        6.1编写测试类

        6.1 增加

        6.2 删除

        6.3 修改

        6.4 查询

                6.4.1模糊查询 

                6.4.2  区间查询

7. 自定义ID生成器

8. 自动填充  

         8.1 数据库新增两个字段(create_time,update_time)

         8.2 实体类新增两个字段(createTime,updateTime)

         8.3 编写Mybatis-Plus自动填充配置类

         8.4 结果

 9.乐观锁

        9.1 数据库新增字段(version)

        9.2  实体类新增字段(version)

        9.3 编写MyBatisPlus的配置类

        9.4 测试 

10.逻辑删除 

        10.1 数据库新增字段(deleted)

        10.2 实体类新增字段(deleted)

        10.3 yml配置 

        10.4 测试 

11. 代码生成器

12.高级条件查询(条件构造器)

        12.1 条件构造器关系介绍

        12.2 介绍 

        12.3 wapper介绍

        12.3 API

        12.4 示例

13.分页插件 

        13.1 编写MyBatisPlus的配置类

        13.2 Page<>对象API

        13.3 示例


写在前面:

  • 下面文章大部分是手敲和官网复制
  • 不喜勿喷

1.Mybatis-Plus简介

官网:MyBatis-Plus

代码托管:Gitee | Github

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

愿景:

我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。

2.特性 
  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

3.支持数据库

任何能使用 MyBatis 进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下,如果不在下列表查看分页部分教程 PR 您的支持。

  • MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb

  • 达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库

4.框架结构

5.快速开始 

        5.1 创建数据库mybatis_plus

现有一张 User 表,其表结构如下:

idnameageemail
1Jone18test1@baomidou.com
2Jack20test2@baomidou.com
3Tom28test3@baomidou.com
4Sandy21test4@baomidou.com
5Billie24test5@baomidou.com

其对应的数据库 Schema 脚本如下: 

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
	name VARCHAr(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAr(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);
-- 真实开发中,version(乐观锁),deleted(逻辑删除)、gmt_create、gem_mo

        5.2 搭建项目

                5.2.1 创建Spring Boot工程

                5.2.2 导入依赖
 
        
            org.springframework.boot
            spring-boot-starter-jdbc
        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            mysql
            mysql-connector-java
            runtime
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.5.1
        
        
        
        
            com.baomidou
            mybatis-plus-generator
            3.5.2
        
        
        
            org.apache.velocity
            velocity-engine-core
            2.3
        
    

                5.2.3 配置yml 
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl   #开启日志打印
    map-underscore-to-camel-case: true    #开启驼峰命名法 数据库中的字段为create_time单词之间用_隔开
  mapper-locations: classpath*:/mapper
@Service
public class UserServiceImpl extends ServiceImpl implements UserService {

}

6.使用Mybatis-Plus简化CURD 

        6.1编写测试类
package com.example.mybatisplusday1;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mybatisplusday1.entity.User;
import com.example.mybatisplusday1.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.sql.Wrapper;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SpringBootTest
class MybatisPlusday1ApplicationTests {
    @Autowired
    private UserMapper usermapper;

}

        6.1 增加
 @Test
    
    void contextLoads() {
        User user = new User();
        user.setName("方哥");
        user.setAge(19);
        user.setEmail("1149876322@qq.com");
        int result = usermapper.insert(user); // 雪花算法帮我们自动生成id
        System.out.println(result); // 受影响的行数
        System.out.println(user); // 发现,id会自动回填
    }

        6.2 删除
   
    @Test
    void delete(){
        //1.按id删除,既可以按id删除,也可以按对象删除
        int result=usermapper.deleteById(1L);
        //int result usermapper.deleteById(User);
        //2.批量删除
        int delete = usermapper.deleteBatchIds(Arrays.asList(1l, 2l, 3l));
        //3.通过map删除
        Mapmap=new HashMap<>();
        map.put("name","方哥");
        int result2=usermapper.deleteByMap(map);
        //条件构造,高级操作
        //usermapper.delete(Wrapper);
    }

        6.3 修改
    
    @Test
    void update(){
        //通过id修改,可以实现动态修改
        User user=new User();
        user.setId(7L);
        user.setName("fang");
        usermapper.updateById(user);
        //通过条件进行修改,高级部分
        //usermapper.update(User,wrapper);
    }

        6.4 查询
    
    @Test
    void select(){
        //1.根据id获取一个User对象
        User user1 = usermapper.selectById(6L);

        //2.按map条件查询
        Mapmap=new HashMap<>();
        map.put("name","fang");
        map.put("age",19);
        List users = usermapper.selectByMap(map);
        //jdk8的lambda表达式 ::方法引用
        users.forEach(System.out::println);
        //3.查询全部
        List users1 = usermapper.selectList(null);
        users1.forEach(System.out::println);
    }

                6.4.1模糊查询 
   
    @Test
    void selectBylike(){
        String name="";
        //wrapper.likeRight();      %在右边
        //wrapper.likeLeft();       %在左边
        //wrapper.like();           %%左右两边都有
        //   wrapper.like(true,"name",name);
        //第一个参数为判断name是否为空为空查全部不为空则按要求查
        QueryWrapperwrapper=new QueryWrapper<>();
        wrapper.like(true,"name",name);
        List users = usermapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

                6.4.2  区间查询
 
    @Test
    void selectByBetween(){
        QueryWrapper wrapper=new QueryWrapper<>();
        wrapper.between("age",15,24);
        //所有的条件拼接默认都是and,只有当自己拼接了or才会以or的方式拼接
        wrapper.or().eq("name","方哥");
        wrapper.orderByDesc("age");
        List users = usermapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

7. 自定义ID生成器

设置实体类中主键自增长类型(默认自动生成类型为UUID)

    @TableId(type = IdType.AUTO)    //设置id为自增长,跟随数据库表中列,默认为UUid需要手动改
    private Long id;

api: 

package com.baomidou.mybatisplus.annotation;

import lombok.Getter;


@Getter
public enum IdType {
    
    AUTO(0),
    
    NONE(1),
    
    INPUT(2),

    
    
    ASSIGN_ID(3),
    
    ASSIGN_UUID(4);

    private final int key;

    IdType(int key) {
        this.key = key;
    }
}

8. 自动填充  

创建时间、修改时间!这些操作一般自动化完成的,我们不希望手动更新!

阿里巴巴开发手册:所有的数据库表:gmt_create、gmt_modified几乎所有表都要配置上!而且需要自动化!

         8.1 数据库新增两个字段(create_time,update_time)

         8.2 实体类新增两个字段(createTime,updateTime)
    // 注意!这里需要标记为填充字段
    //fill = FieldFill.INSERT代表新增是填充
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    // 注意!这里需要标记为填充字段
    //fill = FieldFill.INSERT_UPDATE代表新增修改时填充
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

         8.3 编写Mybatis-Plus自动填充配置类
package com.example.mybatisplusday1.config;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Date;


@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {


    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        //增加的时候实现填充,需要添加两个值
        this.strictInsertFill(metaObject, "createTime", Date.class,new Date()); // 起始版本 3.3.0(推荐使用)
        this.strictInsertFill(metaObject, "updateTime", Date.class,new Date()); // 起始版本 3.3.0(推荐使用)
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        //增加的时候实现填充
        this.strictInsertFill(metaObject, "updateTime", Date.class,new Date()); // 起始版本 3.3.0(推荐使用)
    }
}

         8.4 结果

新增:

修改:

 9.乐观锁

分布式场景下可能会出现脏读  幻读

乐观锁:顾名思义乐观,它总是认为不会出现问题,无论干什么都不去上锁!如果出现问题,再次更新值测试,效率低,容错率高

悲观锁:顾名思义悲观,它总是认为会出现问题,无论干什么都会加上锁!再去操作,效率低,容错率高 

乐观锁实现方式: 

  • 取出记录是,获取当前version
  • 更新事,带上这个version
  • 执行更新事,set version=newVersion where version =oldVersion
  • 如果version不对,就更新失败

        9.1 数据库新增字段(version)

        9.2  实体类新增字段(version)
    
    @Version
    private Integer version;

        9.3 编写MyBatisPlus的配置类
package com.example.mybatisplusday1.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
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;


@Configuration
public class MyBatisPlusConfiguration {
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        //乐观锁配置
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        //分页插件配置
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }
}

        9.4 测试 
   
    @Test
    void testversion(){
        //修改一个用户信息,根据id获取用户信息
        //模拟a用户去修改6L这个数据
        User user1 = usermapper.selectById(6L);
        user1.setName("张三");

        //模拟b用户去修改6L这个数据
        User user2 = usermapper.selectById(6L);
        user2.setName("李四");

        //a先修改用户
        usermapper.updateById(user1);
        //b后修改用户(李四修改失败)
        usermapper.updateById(user2);
    }

10.逻辑删除 

物理删除:从数据库中直接移除

逻辑删除:在数据库中没有被移除,而是通过一个变量来让他失效!delete=0 => delete=1 

管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!订单,不能直接删除的!

        10.1 数据库新增字段(deleted)

        10.2 实体类新增字段(deleted)
    
    @TableLogic
    private Integer deleted;

        10.3 yml配置 
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl   #开启日志打印
    map-underscore-to-camel-case: true    #开启驼峰命名法 数据库中的字段为create_time单词之间用_隔开
  mapper-locations: classpath*:/mapper
    @Test
    void selectBylike(){
        String name="";
        //wrapper.likeRight();      %在右边
        //wrapper.likeLeft();       %在左边
        //wrapper.like();           %%左右两边都有
        //   wrapper.like(true,"name",name);
        //第一个参数为判断name是否为空为空查全部不为空则按要求查
        QueryWrapperwrapper=new QueryWrapper<>();
        wrapper.like(true,"name",name);
        List users = usermapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
    
    @Test
    void selectByBetween(){
        QueryWrapper wrapper=new QueryWrapper<>();
        wrapper.between("age",15,24);
        //所有的条件拼接默认都是and,只有当自己拼接了or才会以or的方式拼接
        wrapper.or().eq("name","方哥");
        wrapper.orderByDesc("age");
        List users = usermapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
}

13.分页插件 

        13.1 编写MyBatisPlus的配置类
package com.example.mybatisplusday1.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
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;


@Configuration
public class MyBatisPlusConfiguration {
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        //乐观锁配置
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        //分页插件配置
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }
}

        13.2 Page<>对象API
package com.baomidou.mybatisplus.extension.plugins.pagination;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import lombok.Setter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;


public class Page implements IPage {

    private static final long serialVersionUID = 8545996863226528798L;

    
    protected List records = Collections.emptyList();

    
    protected long total = 0;
    
    protected long size = 10;

    
    protected long current = 1;

    
    @Setter
    protected List orders = new ArrayList<>();

    
    protected boolean optimizeCountSql = true;
    
    protected boolean searchCount = true;
    
    @Setter
    protected boolean optimizeJoinOfCountSql = true;
    
    @Setter
    protected String countId;
    
    @Setter
    protected Long maxLimit;

    public Page() {
    }

    
    public Page(long current, long size) {
        this(current, size, 0);
    }

    public Page(long current, long size, long total) {
        this(current, size, total, true);
    }

    public Page(long current, long size, boolean searchCount) {
        this(current, size, 0, searchCount);
    }

    public Page(long current, long size, long total, boolean searchCount) {
        if (current > 1) {
            this.current = current;
        }
        this.size = size;
        this.total = total;
        this.searchCount = searchCount;
    }

    
    public boolean hasPrevious() {
        return this.current > 1;
    }

    
    public boolean hasNext() {
        return this.current < this.getPages();
    }

    @Override
    public List getRecords() {
        return this.records;
    }

    @Override
    public Page setRecords(List records) {
        this.records = records;
        return this;
    }

    @Override
    public long getTotal() {
        return this.total;
    }

    @Override
    public Page setTotal(long total) {
        this.total = total;
        return this;
    }

    @Override
    public long getSize() {
        return this.size;
    }

    @Override
    public Page setSize(long size) {
        this.size = size;
        return this;
    }

    @Override
    public long getCurrent() {
        return this.current;
    }

    @Override
    public Page setCurrent(long current) {
        this.current = current;
        return this;
    }

    @Override
    public String countId() {
        return this.countId;
    }

    @Override
    public Long maxLimit() {
        return this.maxLimit;
    }

    
    private String[] mapOrderToArray(Predicate filter) {
        List columns = new ArrayList<>(orders.size());
        orders.forEach(i -> {
            if (filter.test(i)) {
                columns.add(i.getColumn());
            }
        });
        return columns.toArray(new String[0]);
    }

    
    private void removeOrder(Predicate filter) {
        for (int i = orders.size() - 1; i >= 0; i--) {
            if (filter.test(orders.get(i))) {
                orders.remove(i);
            }
        }
    }

    
    public Page addOrder(OrderItem... items) {
        orders.addAll(Arrays.asList(items));
        return this;
    }

    
    public Page addOrder(List items) {
        orders.addAll(items);
        return this;
    }

    @Override
    public List orders() {
        return this.orders;
    }

    @Override
    public boolean optimizeCountSql() {
        return optimizeCountSql;
    }

    public static  Page of(long current, long size, long total, boolean searchCount) {
        return new Page<>(current, size, total, searchCount);
    }

    @Override
    public boolean optimizeJoinOfCountSql() {
        return optimizeJoinOfCountSql;
    }

    public Page setSearchCount(boolean searchCount) {
        this.searchCount = searchCount;
        return this;
    }

    public Page setOptimizeCountSql(boolean optimizeCountSql) {
        this.optimizeCountSql = optimizeCountSql;
        return this;
    }

    @Override
    public long getPages() {
        // 解决 github issues/3208
        return IPage.super.getPages();
    }

    
    public static  Page of(long current, long size) {
        return of(current, size, 0);
    }

    public static  Page of(long current, long size, long total) {
        return of(current, size, total, true);
    }

    public static  Page of(long current, long size, boolean searchCount) {
        return of(current, size, 0, searchCount);
    }

    @Override
    public boolean searchCount() {
        if (total < 0) {
            return false;
        }
        return searchCount;
    }

    
    @Deprecated
    public String getCountId() {
        return this.countId;
    }

    @Deprecated
    public Long getMaxLimit() {
        return this.maxLimit;
    }

    @Deprecated
    public List getOrders() {
        return this.orders;
    }

    @Deprecated
    public boolean isOptimizeCountSql() {
        return this.optimizeCountSql;
    }

    @Deprecated
    public boolean isSearchCount() {
        return this.searchCount;
    }
    

}

        13.3 示例
package com.example.mybatisplusday1.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.mybatisplusday1.entity.User;
import com.example.mybatisplusday1.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;


@RestController
@CrossOrigin        //解决接口跨域问题
public class UserController {
    @Autowired
    private UserService userService;
    
    @GetMapping("/getUserList")
    public Page getUsers(@RequestParam(value = "page",required = true,defaultValue = "1") Integer page,
                               @RequestParam(value = "size",required = true,defaultValue = "3")Integer size,
                               @RequestParam(value = "name",required = false)String name){
       // BaseMapper baseMapper = userService.getBaseMapper();
        Page pageinfo = new Page<>(page,size);
        QueryWrapper queryWrapper = new QueryWrapper<>();
        //判断条件值是否为空,如果不为空拼接条件
        if (!StringUtils.isEmpty(name)){
            //构建条件 模糊查询
            queryWrapper.like("name",name);
        }
        Page page1 = userService.page(pageinfo, queryWrapper);
        //baseMapper.selectPage(pageinfo,queryWrapper);

        return page1;
    }
    //增加
    @PostMapping("/addUser")
    public String addbanana(@RequestBody User user){
        return userService.save(user)+"";
    }
    //删除
    @DeleteMapping("/deleteUser")
    public String deleteUser(@RequestBody User user){
        return userService.removeById(user)+"";
    }
    //修改
    @PutMapping("/updateUser")
    public String updateUser(@RequestBody User user){
        return userService.updateById(user)+"";
    }


}

码字不易,谢谢点赞关注。 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/935965.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号