Spring Cloud集成新版MyBaties-Plus

目录

一.快速开始

1.创建数据库

2.插入数据

3.编写项目,导入依赖

4.配置数据库

5.pojo层:

6.mapper层:

7.编写启动类

8.编写测试类(和application相同路径创建):

8.测试结果:

二.配置日志

三.基础CRUD

1.插入测试

算法选用:

3.更新测试

4.自动填充

1.数据库级别(一般生产上不使用):

2.代码级别:

四.乐观锁插件

1.增加version字段

 2.实体类添加字段

3.注册组件

4.测试

五.查询测试:

1.根据单个id查询:

2.根据多个ID查询:

3.条件查询:

4.分页查询:

1.配置拦截器:

2.编写测试类:

六.删除测试:

1.在数据库增加字段:

2.实体类中添加字段

3.配置:

4.测试删除:


代码生成器等用法在第二个

https://blog.csdn.net/m0_56289903/article/details/122039303?spm=1001.2014.3001.5501

最近在使用mybaties plus,本篇文章基于狂神的教程,地址如下:

【狂神说Java】MyBatisPlus最新完整教程通俗易懂_哔哩哔哩_bilibili笔记资料交流都在我们的平台:www.kuangstudy.com秦疆老师Java进阶系列课程之MyBatisPlus带你走进偷懒的大门;深入浅出的讲解了MyBatisPlus使用的全流程以及实战教学!狂神说Java系列,努力打造通俗易懂的教程QQ交流群 : 664386224https://www.bilibili.com/video/BV17E411N7KN?p=16        但是狂神的版本用的比较老,我就根据他的教程总结了一下新的版本的用法,以及解决了一些比较常见的坑。记录一下,方便查阅

一.快速开始

      通过Mybaties Plus官网可以快速开始

MyBatis-Plushttps://baomidou.com/

1.创建数据库

        首先在数据库中创建一个mybaties_plus数据库:

Spring Cloud集成新版MyBaties-Plus_第1张图片

 导入SQL:

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,gmt_modified

2.插入数据

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');

3.编写项目,导入依赖

在pom中添加依赖:

        
        
            mysql
            mysql-connector-java
            runtime
        

        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.4.3.4
        

        
        
            org.projectlombok
            lombok
            1.18.22
            provided
        
        
        
        
            junit
            junit
            test
        
            
		
        
            org.springframework.boot
            spring-boot-starter-test
            test
        

4.配置数据库

jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&characterEncodeing=utf-8&serverTimezone=GMT%2B8

jdbc:mysql://地址:端口号/数据库名?是否安全连接&unicode&字符集编码&时区配置(mysql8需要配置时区)

5.pojo层:

        pojo层代表简单无规则java对象 纯的传统意义的java对象,最基本的Java Bean只有属性加上属性的get和set方法

        可以额转化为PO、DTO、VO;比如POJO在传输过程中就是DTO

package space.pigeonessence.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName User.java
 * @Description User pojo
 * @createTime 2021年12月14日 09:38:00
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String Email;
}

6.mapper层:

mapper层我们直接继承了BaseMapper,所以不需要繁琐的XML文件了

package space.pigeonessence.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import space.pigeonessence.pojo.User;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName UserMapper.java
 * @Description Mybaties plus Mapper
 * @createTime 2021年12月14日 09:40:00
 */
//持久层
@Repository
public interface UserMapper extends BaseMapper {
    //CRUD编写完成
}

7.编写启动类

package space.pigeonessence;

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

@SpringBootApplication
@MapperScan("space.pigeonessence.mapper")//扫描mapper文件夹

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

8.编写测试类(和application相同路径创建):

package space.pigeonessence;

import org.junit.Test;

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import space.pigeonessence.mapper.UserMapper;
import space.pigeonessence.pojo.User;

import java.util.List;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName MybatiesApplicationTest.java
 * @Description mybaties Unit test
 * @createTime 2021年12月14日 09:43:00
 */
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class MybatiesApplicationTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void contextLoads(){
        List users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}

注意:

此处有一个大坑,官方文档中没有@RunWith(SpringJUnit4ClassRunner.class)注释,但是在微服务项目中,普通的测试类是无法获取bean的,所以会报空指针。加上注释问题解决。

8.测试结果:

 Spring Cloud集成新版MyBaties-Plus_第2张图片

这样,我们的基本快速开始就完成了。

二.配置日志

在bootstrap.yml中进行配置:

   #标准控制台输出日志    
mybatis-plus:   
    configuration:    
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

再进行测试就可以在控制台看到相应的日志了

日志配置也可以用log4j之类的,按照需求进行配置。

三.基础CRUD

了解基础之后,我们利用mybaties可以进行基础的CRUD处理,不用写mapper。

注意:3.0.7版本移除 对 mybatis-plus-generator 包的依赖,自己按需引入。我Mybaitos plus用的版本是3.4.3.4,所以需要引入模板依赖

  
        
            org.apache.velocity
            velocity-engine-core
            2.3
        

1.插入测试

    @Test
    public void testInsert(){
        User user = new User();
        user.setName("PigeonEssence");
        user.setAge(21);
        user.setEmail("[email protected]");

        //直接调用insert函数,不用写mapper
        int insert = userMapper.insert(user);

        System.out.println(insert);//受影响的行数
        System.out.println(user);
    }

我们这里没有设定id,但是可以成功插入:  

Spring Cloud集成新版MyBaties-Plus_第3张图片

 查看表:

Spring Cloud集成新版MyBaties-Plus_第4张图片

 可以看出,mybatiesplus为我们生成了一个id(全局唯一ID) 。

2.主键生成策略

id,一般对应数据库中的主键(primary key)

常用算法有:

        1.uuid

                优点:简单方便,性能好,全球唯一,有利于数据库迁移

                缺点:没有排序,查询效率低(字符串),存储空间大,数据量大,不可读

        2.自增id

                优点:数据库自增列,有利于排序,在数据库的id选择自增,简单易用

                缺点:可能出现单点故障,难以扩展,不好迁移,分库分表比较麻烦

        3.雪花算法

                开源ID生成算法,生成一个LONG类型的id

                前面41bit作为毫秒数,10bit作为机器的ID(5bit是数据中心,5bit机器id),12bit作为毫 秒内的流水号,一个符号位永远是0,几乎可以保证全球唯一

       4.redis

                适合于生成流水号,订单号等,在集成的redis的开发环境中较为实用

                优点:利用redis的单线程实现Id生成,不亦乐乎数据库,灵活方便性能好,数字ID天然排序,对分页有利

                缺点:系统没有redis需要引入,增加复杂度,编码配置工作量大。

        5.zookeeper

算法选用:

我们可以在pojo层中,规划构造器的时候选择id生成策略:

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

我们再IdType中可以看到5类:

package com.baomidou.mybatisplus.annotation;

public enum IdType {
    AUTO(0),
    NONE(1),
    INPUT(2),
    ASSIGN_ID(3),
    ASSIGN_UUID(4);

    private final int key;

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

    public int getKey() {
        return this.key;
    }
}
  • AUTO:主键自增策略(数据库一定要配置自增才能使用)
  • NONE:未设置主键
  • INPUT:手动输入(需要自己写ID)
  • ASSIGN_ID:默认全局唯一id
  • ASSIGN_UUID:全局唯一UUID

3.更新测试

    /*更新测试*/
    @Test
    public void  testUpdate(){
        User user = new User();
        
        //通过条件自动拼接动态sql
        user.setName("PigeonEssence");
        user.setAge(22);
        user.setEmail("[email protected]");

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

        虽然是update by id,但是传入的实际上是一个,也就是User类型,自动拼接动态sql后执行插入成功

Spring Cloud集成新版MyBaties-Plus_第5张图片

4.自动填充

所有的数据库表:gmt_create,gmt_modidied 几乎所有的表都要配置上,需要自动化

两种方式:

1.数据库级别(一般生产上不使用):

  1.在表中新增字段create_time,update_time

        设置默认值为: CURRENT_TIMESTAMP

Spring Cloud集成新版MyBaties-Plus_第6张图片

  2.实体类同步:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private Long id;
    private String name;
    private Integer age;
    private String Email;
    private Date createTime;
    private Date updateTime;
}

3.执行操作 :

在我们执行完更新以后,自动添加了时间戳

2.代码级别:

1.去掉数据库的默认值

2.在实体类上加上标签@TableField

我们可以看到在@TableField中,有一个方法;

FieldFill fill() default FieldFill.DEFAULT;

可以修改数据填充

package com.baomidou.mybatisplus.annotation;

public enum FieldFill {
    DEFAULT,//不操作(默认)
    INSERT,//插入时操作
    UPDATE,//更新时操作
    INSERT_UPDATE;//插入和更新的时候

    private FieldFill() {
    }
}

我们的crate_time是在插入的时候填充的,update_time是在更新的时候填充的,所以修改fill属性:

    @TableField(fill = FieldFill.INSERT)//插入时操作
    private Date createTime;//创建时间

    @TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新的时候操作
    private Date updateTime;//更新时间

3.编写处理器处理

在handler文件创建TimeHandler。


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.util.Date;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName TimeHandler.java
 * @Description  handler for fill
 * @createTime 2021年12月15日 13:46:00
 */
@Slf4j
@Component //处理器一定要加入IOC容器
public class TimeHandler implements MetaObjectHandler {
    //插入时的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill success");
        this.setFieldValByName("createTime",new Date(),metaObject); //设置字段的值
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
    //更新时的填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill success");
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

四.乐观锁插件

乐观锁:十分乐观,认为不会出现问题,无论干什么都不会上锁,出现问题载更新测试

相对的,悲观锁:总是悲观,认为会出现问题,无论什么先上锁再进行操作(影响性能)

主要用法是version(版本号),当我们进行修改的时候,version+1

在操作的时候,拿到版本号,version不对,更新失败

在mybaites中,集成了乐观锁插件:

1.增加version字段

Spring Cloud集成新版MyBaties-Plus_第7张图片

 2.实体类添加字段

    @Version
    private Integer version;//版本锁

3.注册组件

添加一个配置类在config文件夹下(乐观锁插件 | MyBatis-Plus)

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName mbpConfig.java
 * @Description version configuration
 * @createTime 2021年12月16日 13:30:00
 */
@EnableTransactionManagement//自动管理事务
@MapperScan("space.pigeonessence.mapper")//扫描mapper文件夹
@Configuration//配置类
public class mbpConfig {
    /**
     * 新版乐观锁插件
     */
    @Bean
    //拦截器
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
    //注册到插件
}

4.测试

单线程测试:

    @Test
    public void  testMybatisPlusInterceptor(){
        //查询用户信息
        User user = userMapper.selectById(1L);

        //修改用户信息
        user.setName("dashuaige");

        //执行更新
        userMapper.updateById(user);
    }

Spring Cloud集成新版MyBaties-Plus_第8张图片

 我们可以看到,在查询的时候,mybaties plus先查询了version,再进行的update操作

Spring Cloud集成新版MyBaties-Plus_第9张图片

 模拟一下多线程插队的情况:

    /*模拟了多线程插队操作*/
    @Test
    public void  testMybatisPlusInterceptor2(){
        //user1查询用户信息
        User user = userMapper.selectById(1L);
        //user1修改用户信息
        user.setName("ChaoJiDaShuaiGe");
        //模拟多线程:在user1 update操作之前,user2获取到了同一个对象,插队了

        //user2查询用户信息
        User user2 = userMapper.selectById(1L);
        //user2修改用户信息
        user2.setName("NiHaoChouA");
        //user2先执行更新
        userMapper.updateById(user2);
        //user1再执行更新
        userMapper.updateById(user);//没有乐观锁,就会覆盖插队线程的值
    }

我们可以看到这个还是插队线程的值:

Spring Cloud集成新版MyBaties-Plus_第10张图片

具体看着控制台分析一下,这一次的update进行了四次操作:

第一次

 user1查询出来的id为1的对象,找到了他的版本锁是2(之前的测试+了1)

第二次

user2查询出来的id为1的对象,找到了他的版本锁是2(之前的测试+了1)

第三次

user2进行修改参数并且update成功,并且把版本号(version)改成了3

第四次

user1进行修改并且update操作,获取到的版本号3和之前的版本号2不对应,操作失败

 我们可以看到这里的Updates是0.就是受影响的行数为0,更新失败。

五.查询测试:

1.根据单个id查询:

    /*单个ID查询测试*/
    @Test
    public void testSelectById(){
        User user = userMapper.selectById(1L);
        System.out.println(user);
    }

Spring Cloud集成新版MyBaties-Plus_第11张图片

2.根据多个ID查询:

    /*多个ID查询测试*/
    @Test
    public void testSelectByIds(){
        //创建一个id的list
        List idList = Arrays.asList(1, 2, 3);
        //通过list查询对应的id
        List users = userMapper.selectBatchIds(idList);
        //遍历输出
        users.forEach(System.out::println);
    }

Spring Cloud集成新版MyBaties-Plus_第12张图片

3.条件查询:

一般条件查询使用map进行封装

    /*条件查询*/
    @Test
    public void testSelectByMap(){
        //String 对应的是表中的字段名 , Obj,对应的要查的value
        HashMap hashMap = new HashMap<>();
        hashMap.put("name","Jack");
        hashMap.put("age",21);
        List users = userMapper.selectByMap(hashMap);
        //遍历输出
        users.forEach(System.out::println);
    }

上面代码的意思就是我需要查找一个名字叫jack,年龄为21的user

 数据库中的jack是20岁,所以查不到:

年龄改成20之后可以查出来:

 

 我们通过mybatiesplus可以简单的进行多条件查询,自动拼接。

4.分页查询:

1.使用limit进行分页:

2.pagehelper等第三方插件:

3.Mybaties Plus自带分页插件

1.配置拦截器:

我们可以在mybaties的官网中找到最新的插件配置方法:

在2018-06-09之后的版本对插件更新了,我们可以直接在config中配置:

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName mbpConfig.java
 * @Description Interceptor for Plug
 * @createTime 2021年12月16日 13:30:00
 */
@EnableTransactionManagement//自动管理事务
@MapperScan("space.pigeonessence.mapper")//扫描mapper文件夹
@Configuration//配置类
public class mbpConfig {
    @Bean
    //拦截器
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //新版乐观锁插件
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        
        //新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

2.编写测试类:

    /*测试分页查询*/
    @Test
    public void selectByPage(){
        IPage userIPage = new Page<>(1,5);
        userMapper.selectPage(userIPage,null);
        
        long pages = userIPage.getPages();
        long current = userIPage.getCurrent();
        long size = userIPage.getSize();
        long total = userIPage.getTotal();

        System.out.println("一共"+pages+"页, "+"一共"+total+"条数据, "+"当前第"+current+"页, "+"每页显示"+size+"条数据");
        userIPage.getRecords().forEach(System.out::println);
    }

在新版本中,引入了一个IPage的对象,用于代替之前的Page封装,但是使用方式基本不变。

IPage后面的泛型就是你查询的pojo封装。和其他的分页插件没有本质的区别。

查询结果:

Spring Cloud集成新版MyBaties-Plus_第13张图片

六.删除测试:

我们一般吧删除分为两种:

1.物理删除:直接把数据从数据库删除掉。

2.逻辑删除:数据实际没有被删除,通过变量来控制,可以恢复,防止数据丢失(回收站)。

主要说一说逻辑删除:

1.在数据库增加字段:

增加deleted字段,默认0

Spring Cloud集成新版MyBaties-Plus_第14张图片

2.实体类中添加字段

3.3.0之后配置了flag就不用配置@TableLogic

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

3.配置:

在3.1.1后不需要Bean的配置了,2.0需要配置Bean。

在yml中配置:

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

4.测试删除:

    /*测试单个删除*/
    @Test
    public void dele(){
        userMapper.deleteById(1471409312647557121L);
    }

Spring Cloud集成新版MyBaties-Plus_第15张图片

 我们可以看到,虽然执行的是dele操作,实际上是update。

Spring Cloud集成新版MyBaties-Plus_第16张图片

记录没有被删掉,deleted变成了1

测试查询:

Spring Cloud集成新版MyBaties-Plus_第17张图片

 我们可以清楚的看到,sql语句拼接了AND deleted=0,所以修改了之后查不出来,过滤了逻辑删除的数据。

到这里,我们myBaties Plus的增删改查就完成了

你可能感兴趣的:(sql,spring,cloud,java,intellij-idea)