本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

Mybatis-plus介绍及使用

发布于2021-05-29 21:02     阅读(1318)     评论(0)     点赞(12)     收藏(5)


mybatis-plus官方教程:https://mp.baomidou.com/guide/

Mybatis-plus介绍及使用

1、Mybatis-plus简介

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
润物无声
只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。
效率至上
只需简单配置,即可快速进行 CRUD 操作,从而节省大量时间。
丰富功能
热加载、代码生成、分页、性能分析等功能一应俱全。

2、Mybatis-plus坐标

当使用mybatis-plus依赖时导入的坐标:baomidou

<dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-boot-starter</artifactId>
     <version>3.0.5</version>
</dependency>

3、Mybatis-plus入门案例

3.1、创建数据库,创建数据库表

在这里插入图片描述

# 创建表
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)
);

# 插入数据
DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

3.2、创建springboot工程

在这里插入图片描述

3.3、引入入门项目所需的依赖

<!--mybatis-plus-->
 <dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-boot-starter</artifactId>
     <version>3.3.1</version>
 </dependency>

 <!--mysql依赖-->
 <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
 </dependency>

 <!--lombok用来简化实体类-->
 <dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <optional>true</optional>
 </dependency>

3.4、配置数据库信息

在 application.properties 配置文件中添加 MySQL 数据库的相关配置

  • spring boot 2.0(内置jdbc5驱动)
#mysql数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
  • spring boot 2.1及以上(内置jdbc8驱动)
    注意:driver和url的变化
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root

在这里插入图片描述

3.5、编写代码

3.5.1、实体类:

在这里插入图片描述

@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

在这里插入图片描述

3.5.2、添加mapper

创建包 mapper 编写UserMapper 接口: UserMapper.java

在这里插入图片描述

@Repository
public interface UserMapper extends BaseMapper<User> {
}

3.5.3、启动类添加注解@MapperScan

作用:指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类

添加位置:是在Springboot启动类上面添加.

@SpringBootApplication
@MapperScan("com.study.demomptest.mapper")
public class DemomptestApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemomptestApplication.class, args);
    }

}

3.6、测试

3.6.1、查询user表中所有数据

@SpringBootTest
class DemomptestApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    void findAll() {
        List<User> users = userMapper.selectList(null);
        System.out.println(users);
    }

}

在这里插入图片描述

3.6.2、新增

在这里插入图片描述

@SpringBootTest
class DemomptestApplicationTests {
    @Autowired
    private UserMapper userMapper;

    //新增
    @Test
    void insert(){
        User user = new User();
        user.setName("Lucy");
        user.setAge(20);
        user.setEmail("12345@qq.com");
        int insert = userMapper.insert(user);
        System.out.println(insert);
    }
 }

3.6.3、修改数据

在这里插入图片描述

4、要想在控制台看到sql输出日志,需要在application.properties配置文件中添加以下代码

#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

5、主键生成策略

  • auto-increment
  • uuid:每次随机生成唯一值,排序不方便
  • redis
  • mybatis-plus (使用了snowplake算法)

5.1、常见的主键生成策略介绍

https://www.cnblogs.com/haoxinyue/p/5208136.html

5.2、 Mybatis-plus默认主键生成策略

mybatis-plus默认只用自己自带的主键生成策略,MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法)

@TableId(type = IdType.ASSIGN_ID)
private String id;
  • 雪花算法:分布式ID生成器
    雪花算法是由Twitter公布的分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的主键的有序性。
  • 核心思想:
    长度共64bit(一个long型)。
    首先是一个符号位,1bit标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0。
    41bit时间截(毫秒级),存储的是时间截的差值(当前时间截 - 开始时间截),结果约等于69.73年。
    10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID,可以部署在1024个节点)。
    12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID)。
    在这里插入图片描述
  • 雪花算法优点:
    整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞,并且效率较高。

5.3、 自定义主键生成策略

可以自己设置要使用的主键生成策略,使用如下注解@TableId

  • @TableId(type = IdType.ID_WORKER)
    mybatis-plus自带的策略,生成19位值,当属性类型类数字类型时使用该策略,比如Long

  • @TableId(type = IdType.ID_WORKER_STR)
    mybatis-plus自带的策略,生成19位值,当属性类型类字符串类型时使用该策略,比如String
    在这里插入图片描述

  • @TableId(type = IdType.UUID)
    随机生成唯一值

  • @TableId(type = IdType.AUTO)
    数据库ID自增

  • @TableId(type = IdType.INPUT)
    用户输入ID, 该类型可以通过自己注册自动填充插件进行填充

  • @TableId(type = IdType.NONE)
    没有策略

    在需要设置主键的实体类属性上使用该注解,可以设置主键策略,主要有以下几种策略。
    在这里插入图片描述

5.4、全局主键配置

要想影响所有实体的配置,可以设置全局主键配置

#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto

6、mbatis-plus自动填充

需求描述:
项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。
我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作

6.1、数据库修改

在User表中添加datetime类型的新的字段 create_time、update_time

6.2、实体类修改

在实体类里需要自动填充的属性上面添加注解
如在下面User实体类的createTime和updateTime属性上添加注解
在这里插入图片描述

6.3、实现元对象处理器接口

创建类,实现MetaObjectHandler接口,实现接口里的方法

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

import java.util.Date;

/**
 * @Description :
 * @Author :lenovo
 * @Date :2021/2/20 21:34
 */
 @Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    //用mybatis-plus实现添加操作时,在这个方法会执行
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    //用mybatis-plus实现修改操作时,在这个方法会执行
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

7、丢失更新

什么是丢失更新:
多个人同时需改一条记录,最后提交的会把之前提交的数据覆盖更新。
在这里插入图片描述

7.1、丢失更新解决方案

7.1.1 、悲观锁(表级锁):串行操作。

举例1:如上图修改数据,Lucy修改money数据时,别人都不能进行操作,只有lucy操作完成后,其他人才能操作。
举例2:又比如当一个人上网浏览新闻时,别人不能浏览,只有当这个人浏览完成后,别人才能浏览,如果这个人浏览一百年,其他所有人就要等一百年,这就是悲观锁。

7.1.2、 乐观锁

  • 主要适用场景:当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新

  • 使用版本号进行并发的控制。比如多个人修改数据时,只有一个人才能修改成功,其他人不能同时修改。
    在这里插入图片描述乐观锁的实现原理:
    在这里插入图片描述乐观锁的具体实现:
    mybatis-plus实现乐观锁官方步骤:https://mp.baomidou.com/guide/interceptor-optimistic-locker.html#optimisticlockerinnerinterceptor

  • 1、表中添加字段,作为乐观锁版本号。
    在这里插入图片描述

  • 2、对应实体类添加版本号属性。
    在这里插入图片描述
    @TableField(fill = FieldFill.INSERT): 插入数据时自动填充数据
    在这里插入图片描述

@version注解所在的包:
在这里插入图片描述

  • 3、插件配置

spring工程:在spring.xml配置文件中

<bean class="baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>

spring-boot项目:新建一个存放配置类的包,在该包下新建个配置类:编写乐观锁插件

 package com.nonglin.mpdemo.config;

import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("com.nonglin.mpdemo")
public class Mpconfig {

    //乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}

  • 4、在测试类中测试乐观锁:
  //测试乐观锁
    @Test
    public void testOptimisticLocker(){
        User user = userMapper.selectById(1363307390618947585L);
        user.setAge(1);
        int row = userMapper.updateById(user);
        System.out.println("修改"+row+"条数据");
    }

8、mybatis-plus简单查询

8.1、过多个id批量查询selectBatchIds

Zero date value prohibited解决方法

 //多个id批量查询
    @Test
    public void findByBatchIds(){
        List<User> users = userMapper.selectBatchIds(Arrays.asList(1L,2L,3L));
        for(User user:users){
            System.out.println(user);
        }
    }

控制台输出:
在这里插入图片描述

JDBC Connection [HikariProxyConnection@1171672359 wrapping com.mysql.cj.jdbc.ConnectionImpl@34fe326d] will not be managed by Spring
==>  Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id IN ( ? , ? , ? ) 
==> Parameters: 1(Long), 2(Long), 3(Long)
<==    Columns: id, name, age, email, create_time, update_time, version
<==        Row: 1, Jone, 18, test1@baomidou.com, null, null, null
<==        Row: 2, Jack, 120, test2@baomidou.com, null, null, null
<==        Row: 3, Tom, 28, test3@baomidou.com, null, null, null
<==      Total: 3
打印输出:
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@65eabaab]
User(id=1, name=Jone, age=18, email=test1@baomidou.com, createTime=null, updateTime=null, version=null)
User(id=2, name=Jack, age=120, email=test2@baomidou.com, createTime=null, updateTime=null, version=null)
User(id=3, name=Tom, age=28, email=test3@baomidou.com, createTime=null, updateTime=null, version=null)

8.2、简单的条件查询selectByMap

 //简单条件查询
    @Test
    public void testSelectByMap(){
        HashMap<String,Object> map = new HashMap<>();
        map.put("name","Lucy");
        map.put("age",18);
        List<User> users = userMapper.selectByMap(map);
        users.forEach(System.out::println);
    }

控制台输出:
在这里插入图片描述

JDBC Connection [HikariProxyConnection@774095232 wrapping com.mysql.cj.jdbc.ConnectionImpl@499683c4] will not be managed by Spring
==>  Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user WHERE name = ? AND age = ? 
==> Parameters: Lucy(String), 18(Integer)
<==    Columns: id, name, age, email, create_time, update_time, version
<==        Row: 1363104207493660674, Lucy, 18, Lucy@qq.com, null, null, null
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2b917fb0]
User(id=1363104207493660674, name=Lucy, age=18, email=Lucy@qq.com, createTime=null, updateTime=null, version=null)

9、mybatis-plus分页

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能
(1)创建配置类
在配置类中添加插件

 //分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

(2)测试selectPage分页
测试:最终通过page对象获取相关数据

@Test
void textPage(){
     Page<User> page = new Page(1,3);
     Page<User> userPage = userMapper.selectPage(page, null);
     //返回的对象得到分页的所有数据
     long current = userPage.getCurrent();//当前显示的页码
     long size = userPage.getSize();//每页显示记录数
     List<User> records = userPage.getRecords();//当前页数据的集合
     long pages = userPage.getPages();//表中数据的总页数
     long total = userPage.getTotal();//数据库表中的总记录数
     boolean hasPrevious = userPage.hasPrevious();//是否有上一页
     boolean hasNext = userPage.hasNext();//是否有下一页

     //通过page对象获取分页数据
     System.out.println("当前页:"+current);//当前页
     System.out.println("每页显示记录数:"+size);//每页显示记录数
     System.out.println("当前页数据的集合:"+records);//当前页数据的list集合
     System.out.println("数据库表中数据总页数:"+pages);//总页数
     System.out.println("数据库表中的总记录数:"+total);//总记录数
     System.out.println("是否有上一页:"+hasPrevious);//是否有上一页
     System.out.println("是否有下一页:"+hasNext);//是否有下一页
 }

控制台输出:
在这里插入图片描述

9、mybatis-plus删除

9.1、物理删除

真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据。

 //根据id删除
    @Test
    public void deleteById(){
        int result = userMapper.deleteById(1363126056508198913L);
        System.out.println(result);
    }

    //批量删除
    @Test
    public void testDeleteBatchIds(){
        int result = userMapper.deleteBatchIds(Arrays.asList(1L,2L,3L));
        System.out.println(result);
    }

    //根据条件删除
    @Test
    void testDelete(){
        HashMap map = new HashMap();
        map.put("name","LucyTest");
        map.put("age",23);
        int i = userMapper.deleteByMap(map);
        System.out.println("成功删除了"+i+"条数据");

    }

9.2、逻辑删除

假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录。

逻辑删除的使用场景:

  • 可以进行数据恢复
  • 有关联数据,不便删除

9.2.1、表添加逻辑删除字段,对应实体类添加属性,属性添加注解。

在这里插入图片描述在这里插入图片描述

9.2.2、在自动填充中给删除加个初始值:

在这里插入图片描述

9.2.3、在项目的配置类中配置逻辑删除插件

(mp3.3版本之后不需要引入该插件页可以实现功能)

    //逻辑删除插件
    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }

9.2.4、application.properties 加入配置

#逻辑删除配置
mybatis-plus.global-config.db-config.logic-not-delete-value=0
mybatis-plus.global-config.db-config.logic-delete-value=1

9.2.5、测试逻辑删除

/**
 * 测试 逻辑删除
 */
@Test
public void testLogicDelete() {
    int result = userMapper.deleteById(1L);
    System.out.println(result);
}
  • 测试后发现,数据并没有被删除,deleted字段的值由0变成了1
    在这里插入图片描述

  • 测试后分析打印的sql语句,是一条update
    在这里插入图片描述

  • 注意:被删除数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作

10、mybatis-plus性能分析

性能分析拦截器,用于输出每条 SQL 语句及其执行时间
SQL 性能执行分析,开发环境使用,超过指定时间,停止运行。有助于发现问题。

10.1、配置插件

(1)参数说明

  • 参数:maxTime: SQL 执行最大时长,超过自动停止运行,有助于发现问题。
  • 参数:format: SQL是否格式化,默认false。

(2)在 MybatisPlusConfig 中配置插件
注意:该插件在3.2.0以上版本移除,推荐使用使用第三方拓展执行SQL分析(需在pom.xml导入p6spy 依赖)打印功能

/**
 * SQL 执行性能分析插件
 * 开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长
 */
    @Bean
    @Profile({"dev","test"})// 设置 dev test 环境开启
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(100);//ms,超过此处设置的ms则sql不执行
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }

(3)Spring Boot 中设置dev环境,在springboot配置文件中设置

#环境设置:dev、test、prod
spring.profiles.active=dev

10.2、测试

/**
 * 测试 性能分析插件
 */
@Test
public void testPerformance() {
    User user = new User();
    user.setName("我是Helen");
    user.setEmail("helen@sina.com");
    user.setAge(18);
    userMapper.insert(user);
}

11、mybatis-plus实现复杂条件查询

11.1、Wapper介绍

在这里插入图片描述Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
QueryWrapper : 查询条件封装
UpdateWrapper : Update 条件封装
AbstractLambdaWrapper : 使用Lambda 语法
LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper : Lambda 更新封装Wrapper

在这里插入图片描述

11.2、MyBatis-plus复杂条件查询测试用例-使用QueryWrapper

Mybatis-plus条件构造器官方文档

1. ge、gt、le、lt、isNull、isNotNull

@Test
public void testQuery() {
QueryWrapper<User>queryWrapper = newQueryWrapper<>();
queryWrapper
        .isNull("name")
        .ge("age", 12)
        .isNotNull("email");
    int result = userMapper.delete(queryWrapper);
System.out.println("delete return count = " + result);
}

2. eq、ne

注意:seletOne()返回的是一条实体记录,当出现多条时会报错

@Test
public void testSelectOne() {
	QueryWrapper<User>queryWrapper = newQueryWrapper<>();
	queryWrapper.eq("name", "Tom");
	Useruser = userMapper.selectOne(queryWrapper);//只能返回一条记录,多余一条则抛出异常
	System.out.println(user);
}

3. between、notBetween:包含大小边界

@Test
public void testSelectCount() {
	QueryWrapper<User>queryWrapper = newQueryWrapper<>();
	queryWrapper.between("age", 20, 30);
    Integer count = userMapper.selectCount(queryWrapper); //返回数据数量
	System.out.println(count);
}

4. like、notLike、likeLeft、likeRight

selectMaps()返回Map集合列表,通常配合select()使用

@Test
public void testSelectMaps() {
	QueryWrapper<User>queryWrapper = newQueryWrapper<>();
	queryWrapper
       	    .select("name", "age")
        	.like("name", "e")
        	.likeRight("email", "5");
	List<Map<String, Object>>maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表
	maps.forEach(System.out::println);
}

5. orderBy、orderByDesc、orderByAsc

@Test
public void testSelectListOrderBy() {
QueryWrapper<User>queryWrapper = newQueryWrapper<>();
queryWrapper.orderByDesc("age", "id");
List<User>users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}

11.3、使用LambdaQueryWrapper完成复杂条件查询

LambdaQueryWrapper完成复杂条件查询

原文链接:https://blog.csdn.net/qq_46112274/article/details/117287549



所属网站分类: 技术文章 > 博客

作者:听说你很拽

链接:http://www.javaheidong.com/blog/article/207454/4008207dfcd5d38bc1ef/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

12 0
收藏该文
已收藏

评论内容:(最多支持255个字符)