mybatis-plus

mybatis-plus

目录:

1:mybatis-plus入门

官网:http://mp.baomidou.com/

参考教程:https://mp.baomidou.com/guide/wrapper.html#abstractwrapper

mybatis-plus是一个mybatis的增强工具,在mybatis的基础上之作增强不做改变,为简化开发、提高效率而生。

使用步骤:

**1:**开始创建数据库(mybatis_plus),创建数据库表,添加数据,用于mp操作

数据表创建:

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)
);

其对应的数据库Data脚本如下:那个user表中

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');

**2:**创建一个springboot(2.3.0)工程(myplus)

**3:**添加springboot和mybatis-plus依赖

spring-boot-starter、spring-boot-starter-test:其内本身就有

添加:mybatis-plus-boot-starter、MySQL、lombok

lombok:不用写get和set方法,只需要添加个注解就行

不过这玩意还是有点麻烦,可以自动创建springboot,进行勾选,即可以省去这一步骤

 <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1.tmp</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>

**4:**安装lombok插件

IDEA–File–setting–Plugins–输入lombok–下载–重启IDEA

**5:**创建application.properties,并作配置(当然,yml配置文件也可以)

当然,springboot中,其本来是有的。在其内添加:(mysql数据库连接)

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimeZone=GMT%2BB
spring.datasource.username=root
spring.datasource.password=123456

注:这是2.1以后版本所用,添加了:cj serverTimezone=GMT%2BB(时区)

**6:**创建类,编写代码

在main的那com…下面创建一个entity的包,用来存放实体类;创建一个mapper的包,这是mybatis-plus中的。

在entity包创建一个实体类User,添加:

@Data   //不用添加get and set和toString方法了
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

在mapper下建立UserMapper接口,且让其继承自BaseMapper:这样就可以调用BaseMapper中的增删改查方法,不用再弄xml。:使其都为User类中的类型

package com.zpc.myplus.mapper;

@Repository   //用来声明对象,来使测试的时候不报错
public interface UserMapper extends BaseMapper<User> {

}

在springboot的那个主文件中,添加: 以此来使主程序找到mapper这个接口

@MapperScan("com.zpc.myplus.mapper")

其主文件:

package com.zpc.myplus;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("com.zpc.myplus.mapper")
@SpringBootApplication      //springboot启动类
public class MyplusApplication {

    public static void main(String[] args) {

        SpringApplication.run(MyplusApplication.class, args);
    }

}

7:测试

接下来,在测试类(test下的)测试下: (不用在程序中写此代码,这是为了测试)

@Autowired  //将其注入
    private UserMapper userMapper;  //用来调用UserMapper中的方法

    //查询user表中的所有属性
    @Test
    public void findAll() {
        List<User> users = userMapper.selectList(null);      
        //先输入userMapper.,后面会出现一系列方法,由于此方法返回的是List集合,且其内有参数,故给参数赋值null,再在其后”.var“,让其返回所有东西
        System.out.println(users);

即可查出

注:查看sql输出日志,更直观化的查看数据库中的内容

在配置文件

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
2:mybatis-plus添加操作

当然,其id是默认配置的,下节说id问题

userMapper.insert返回的是一个user,故而在之前实例化user,再对其添加

//添加操作
    @Test
    public void addUser(){
        User user=new User();
        user.setName("名");
        user.setAge(11);
        user.setEmail("122@qq.com");
        
        int insert = userMapper.insert(user);
        System.out.println("s" +insert);

    }
3:mybatis-plus主键生成策略介绍

参考资料:https://www.cnblogs.com/haoxinyue/p/5208136.html

主动策略:

1:自动增长,AUTO INCREMENT

​ 1-10000 10001-20000 20001-30000

​ 缺点:分表分库时会比较麻烦。比如,下一张表id需要再上一个最后一个id的基础上加一

2:UUID

​ 每次生成随机唯一的值

​ 缺点:排序不方便

3:redis生成id

​ 可以使用Redis集群来获取更高的吞吐量。假如一个集群中有5台Redis。可以初始化每台Redis的值分别是1,2,3,4,5,然后步长都是5。各个Redis生成的ID为:

A:1,6,11,16,21

B:2,7,12,17,22

C:3,8,13,18,23

D:4,9,14,19,24

E:5,10,15,20,25

​ 缺点:1)如果系统中没有Redis,还需要引入新的组件,增加系统复杂度。

​ 2)需要编码和配置的工作量比较大。

4:mp自带策略(默认策略)(Twitter的snowflake算法

生成一个19位的值

snowflake(雪花)是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。具体实现的代码可以参看https://github.com/twitter/snowflake。

在主键id上方加:

@TableId(type = IdType.AUTO)
private Long id;

注:那个点后面:

AUTO:自动增长

ID_WORKER:mp自带策略,生成19位值,数字类型使用这种策略,比如long(说的是主键的)

ID_WORKER_STR: mp自带策略,生成19位值,字符串类型使用这种策略,比如String(说的是主键的)

INPUT:设置ID值

NONE:输入

UUID:随即唯一值

4:mybatis-plus实现自动填充

配置实体类中相关字段的自动填充策略,在@TableField注解中设置fill属性

DEFAULT:默认不处理

INSERT:插入填充字段

UPDATE:更新填充字段

INSERT_UPDATE:插入和更新填充字段

修改操作

//修改操作
    @Test
    public void updateUser(){
        User user=new User();
        user.setId(2L);   //根据id改,其主键id是long类型
        user.setAge(100);

        int i = userMapper.updateById(user);
        System.out.println(i);
        
    }

这样的修改只是弄了要修改的,比如只是修改了id为2对应的年龄,但其对应的其他的却没有修改。故而,就有了自动填充!

运行结果 如:

==> Preparing: UPDATE user SET age=? WHERE id=?
> Parameters: 100(Integer), 2(Long)
<
Updates: 1

自动填充

1:先给数据表添加两个字段:create_time (创建时间) update_time (更新时间),其类型都选datetime

2:添加实体类属性:User

驼峰命名法

private Data createTime;   //create_time
private Data updateTime;   //update_time

现在,更改上一次添加的数据,运行后,就会发现,create_time和update_time还是null,借此,就说到了mp的自动填充:不需要set到对象里面值,使用mp方式实现数据添加

如:以前mybatis的:手动添加

//添加操作
    @Test
    public void addUser(){
        User user=new User();
        user.setName("tian");
        user.setAge(14);
        user.setEmail("1223@qq.com");

        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        int insert = userMapper.insert(user);
        System.out.println("s" +insert);

    }

自动填充:

第一步:在实体类里面进行自动填充属性添加注解

    @TableField(fill = FieldFill.INSERT)   //INSERT添加
    private Data createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)   //INSERT_UPDATE添加和修改的时候里面都有值
    private Data updateTime;

第二步:先随便创建个包(这个随意),创建类,实现接口 MetaObjectHandler,实现接口里面的方法.

@Component  //表示交给spring去管理
public class MyMetaObjectHandler implements MetaObjectHandler {

    //使用mp实现一个添加的操作,这个方法就会执行
    @Override
    public void insertFill(MetaObject metaObject) {


        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    //使用mp实现修改操作,这个方法会执行
    @Override
    public void updateFill(MetaObject metaObject) {

        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}
5:mybatis-plus实现乐观锁

解决丢失更新问题(当要更新一条记录的时候,希望这条记录没有被别人更新)

丢失更新(多个人同时去修改同一条记录,最后提交的那个,会把之前提交的都给覆盖掉)

问题解决:悲观锁(串行):同一个东西,只能一个人同时操作

​ 乐观锁:取出记录时,获取当前version(版本号)

​ 更新时,带上这个version(更新完成后,版本号会变化)

​ 执行更新时,set version=newVersion where version=oldVersion

​ 如果version不对,就更新失败

1:在表里面加一个version(int型),意为版本号

2:对应实体类(User)添加版本号属性

在实体类版本号属性上添加注解

@Version
private Integer version;//版本号

3:配置乐观锁插件

一:如果是spring xml:添加这即可

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

二:如果是spring boot:

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

注:建立一个配置类(存放所有的配置):

​ 先创建个包config(存储所有的配置类),再创建mp的配置类:MpConfig

​ 添加一个@Configuration,再把配置放进去。再把启动类中的中的@MapperScan(“com.zpc.myplus02.mapper”)添加过来

​ 注:只要是属于mp的配置,皆可放在这里

package com.zpc.myplus02.config;
//包省略
@Configuration
@MapperScan("com.zpc.myplus02.mapper")    //以此来使主程序找到mapper这个接口
public class MpConfig {

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

}

4:这步在开发中可省略(这玩意是为理解)

给version一个初始值,先在实体类User中

@TableField( fill = FieldFill.INSERT)   //INSERT添加
@Version
private Integer version;//版本号

再在MyMetaObjectHandler,的那个insertFill方法中,添加一个自动填充,让其初始值为1

this.setFieldValByName("updateTime",1,metaObject);
6:mybatis-plus实现分页
6.1:简单查询

1:根据id查询

User user=userMapper.selectById(123442)

2:多个Id查询

//多个id查询
    @Test
    public void moreid(){
        List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));
        System.out.println(users);
    }
6.2:分页查询

1:放插件,放入MpConfig

@Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }

2:在测试类中

编写分页代码,new page对象,传入两个参数(当前页和每页显示记录数),调用mp方法实现分页查询

    //分页查询
    @Test
    public void testPage(){
        //new page,传入当前页和每页显示记录数
        Page<User> page=new Page<>(1,3);
        //把分页所有数据封装到page对象中
        userMapper.selectPage(page,null);
        
        System.out.println(page.getCurrent());   //当前页
        System.out.println(page.getRecords());   //每页数据list集合
        System.out.println(page.getSize());      //每页数据记录数
        System.out.println(page.getTotal());     //总记录数
        System.out.println(page.getPages());     //总页数
        System.out.println(page.hasNext());      //是否存在下一页
        System.out.println(page.hasPrevious());  //是否存在上一页

    }
7:mybatis-plus实现逻辑删除

逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改成"被删除状态"(deleted值就为1),之后在数据库中仍旧能看到此条数据记录

7.1:简单删除

1:根据id删除(物理删除)

@Test   //物理删除
public void testDeleteById(){
    int result=userMapper.deleteById(3L);
    System.out.println(result);
}

2:批量删除()

@Test
public void testDeleteBatchIds(){
    int result=userMapper.deleteBatchIds(Arrays.asList(1,2,3));
    System.out.println(result);
}
7.2:逻辑删除

表中数据看起来还在,不过查询查不出来

1:给表中添加字段deleted(tinyint类型),并将其默认值(Default)填为0

​ 再在实体类中添加属性,并附上注解

@TableLogic
private Integer deleted;//逻辑删除的值

如果每有设置默认值,那就在MyMetaObjectHandler,的那个insertFill方法中,添加一个自动填充,让其初始值为0

        //添加逻辑删除的默认值0
        this.setFieldValByName("deleted",0,metaObject);

2:配置逻辑删除插件,在mpconfig

@Bean
public ISqlInjector sqlInjector(){
    return new LogicSqlInjector();
}

3:在配置文件中加入(可以不加,因为这是默认的)

​ 即代表,删除时值(Default)为1,不删除时值为0

mabatis-plus.global-config.db-config.logic-delete-value=1
mabatis-plus.global-config.db-config.logic-not-delete-value=0 

4:在测试文件中,还是用物理删除的那个,不过其效果已经变成了逻辑删除

@Test    
public void testDeleteById(){
    int result=userMapper.deleteById(3L);
    System.out.println(result);
}
8:性能分析

性能分析拦截器,用于输出每条SQL语句及其执行时间

SQL性能分析,开发环境使用,超过指定时间,停止运行。有助于发现问题

1:在配置类中mpconfig

​ 注:三种环境:dev:开发环境

​ test:测试环境

​ prod:生产环境(结束后加)

/*
*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;
}

2:spring boot中设置dev环境

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

执行查询后,如果时间超过设置的那个时间,就会报错,且不执行其

9:mybatis-plus实现条件查询

mp中实现条件查询,一般都使用QueryWrapper

步骤:创建QueryWrapper对象

​ 调用里面的方法实现各种查询(https://mp.baomidou.com/guide/wrapper.html#abstractwrapper)

注:这只是一部分,具体可在上方官网查询

ge(大于等于)eq(等于)ne(不等于)gt(大于)lt(小于)le(小于等于)

    @Test
    public void testSelectQuery(){
        //创建QueryWrapper对象
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        //查询age>=30记录
        wrapper.ge("age",30);
        List<User> users=userMapper.selectList(wrapper);
        System.out.println(users);
    }

between(BETWEEN 值1 AND 值2):范围

    @Test
    public void testSelectQuery(){
        //创建QueryWrapper对象
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        //查询age在30到40之间记录
        wrapper.beteen("age",30,40);
        List<User> users=userMapper.selectList(wrapper);
        System.out.println(users);
    }

like(模糊查询)

//查询名字中包含于的
wrapper.like("NAME","于");

orderByDesc/Asc(排序)

last(直接拼接到sql的最后)

wrapper.last("limit 1");

select(指定要查询的列)

//只会查出来id和name
wrapper.select("id","name")
  List<User> users=userMapper.selectList(wrapper);
    System.out.println(users);
}

between(BETWEEN 值1 AND 值2):范围

```java
    @Test
    public void testSelectQuery(){
        //创建QueryWrapper对象
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        //查询age在30到40之间记录
        wrapper.beteen("age",30,40);
        List<User> users=userMapper.selectList(wrapper);
        System.out.println(users);
    }

like(模糊查询)

//查询名字中包含于的
wrapper.like("NAME","于");

orderByDesc/Asc(排序)

last(直接拼接到sql的最后)

wrapper.last("limit 1");

select(指定要查询的列)

//只会查出来id和name
wrapper.select("id","name")

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值