Mybatis-Plus

Posted aBiu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis-Plus相关的知识,希望对你有一定的参考价值。

参考地址:https://mp.baomidou.com/guide/quick-start.html

快速入手:

SpringBoot项目依赖:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.2.RELEASE</version>
    <relativePath/>
</parent>

引入 spring-boot-starterspring-boot-starter-testmybatis-plus-boot-starterlombok依赖:

     <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

在 application.yml 配置文件中添加相关配置:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=root

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

在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:

@MapperScan("com.biao.mapper")
@SpringBootApplication
public class MybatisPlusApplication {

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

编写实体类 User.java(此处使用了 Lombok 简化代码)

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

编写Mapper类

// mapper 接口继承一个接口,BaseMapper
public interface UserMapper extends BaseMapper<User> {

}

在测试类测试:

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelect() {
        System.out.println(("----- selectAll method test ------"));
        List<User> userList = userMapper.selectList(null);
        Assert.assertEquals(5, userList.size());
        userList.forEach(System.out::println);
    }

测试完毕,那么,这些sql 是谁写的呢?

配置日志

所有的sql现在是不可见的,如果要知道它是怎么执行的,就要看日志。

只需要一行,在配置文件添加: mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl 

CRUD 扩展

所有sql 都是自动 动态配置的

插入测试

public void insert(){
        User user = new User();
        user.setName("wangbiao");
        user.setAge(3);
        user.setEmail("1371850216@qq.com");
        // 没有set id,它会自动生成id
        // 数据库插入的默认id,是全局唯一的
        int insert = userMapper.insert(user);
    }

id 生成策略

uuid   自增id  雪花算法  redis  zookeeper

参考地址:https://www.cnblogs.com/haoxinyue/p/5208136.html

Twitter的snowflake算法

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

修改方法

public void update(){
        User user = new User();
        user.setId(123L);   // 根据id 修改数据
        user.setName("aBiu~");
        int i = userMapper.updateById(user);

 }

填充策略

设置数据库对应的实体类:

@Data
public class User {
    @TableId(type = IdType.ASSIGN_ID)   // 默认就是这个
    private Long id;
    
    private String name;
    private Integer age;
    private String email;
    
    @TableField(fill = FieldFill.INSERT)    // 设置新增时间
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)     // 设置修改时候,新增时间也要添加
    private Date updateTime;
}

既然设置了新增,要配置,写个handler 的配置类并重写两个方法:

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    // 插入时的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        // 根据实体类的 createTime updateTime 字段,添加或 修改数据时执行这个方法,添加一个时间
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
    // 修改时的填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        // 修改时只修改 修改时间的字段数据
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

乐观锁机制

实现方式:

取出记录时,获取当前 version 

更新时,带上这个 version

执行更新时,set version,where 判断version 版本

如果version 版本不对,就更新失败。

乐观锁插件

1、给数据库增加version 字段,设置默认值1,就是初始时给 1

2、给对应的实体类添加属性字段,增加注解:@Version

    @Version
    private Integer version;

3、注册组件

在config 包里配置,写一个MyBatisPlusConfig

// 事务注解
@EnableTransactionManagement
@Configuration
public class MyBatisPlusConfig {

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

}

分页查询

1、配置拦截器:

官网代码:

//Spring boot方式
@Configuration
@MapperScan("com.baomidou.cloud.service.*.mapper*")
public class MybatisPlusConfig {

    @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;
    }
}

我们只需要在配置文件写个方法,写一行代码即可;找到那个配置类

// 事务注解
@EnableTransactionManagement
@Configuration
public class MyBatisPlusConfig {

    // 注册乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
    // 分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }

}

2、测试

  // 测试分页查询
    public void testPage(){
        // 第一页,每一页显示5条数据
        Page<User> page = new Page<>(1, 5);
        userMapper.selectPage(page,null);

        page.getRecords().forEach(System.out::println);
    }

这个page 有很多方法,比如上一页下一页总数。。。

删除操作

mapper 可以直接点 出来删除方法,通过id,map,批量,三种删除方式,直接执行即可

通过id删除: userMapper.deleteById(1L); 

通过id批量删除: userMapper.deleteBatchIds(Arrays.asList(1,2,3)); 

通过map删除:

     HashMap<String, Object> map = new HashMap<>();
        // name 是属性,数据库字段
        map.put("name","wangbiao");
        userMapper.deleteByMap(map);

 逻辑删除

在数据库中没有被删除,只是通过一个变量来让它失效。

1、在数据库表中添加一个deleted 字段,实体类中添加一个相应的属性,不要忘记加注解 @TableLogic

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

2、配置:

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

 3、再次执行删除: userMapper.deleteById(1L); 

就是逻辑删除,不会真正删除,记录依旧在数据库,但是值已经发生变化。

但是再次查询这条数据,会查不到的,自动会过滤掉逻辑删除的。

条件构造器(重点)

一些复杂的sql 就可以使用它来代替。

参考地址:https://mp.baomidou.com/guide/wrapper.html#abstractwrapper

示例:返回多条数据

  public void test(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.isNotNull("name")       // name 不为空的
                .isNotNull("email")     // email 不为空的
                .ge("age",21);      // age 大于21 的,但是好像等于21 的也会查出来
        userMapper.selectList(wrapper).forEach(System.out::println);
    }

还有很多条件可以加,like(模糊)、orderBy(排序)等等,很多,

参考官方地址:https://mp.baomidou.com/guide/wrapper.html#eq

示例2:查询一条数据的:如果明知道是查出来的是多条数据,就不要用这个

  public void test(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name","wangbiao");      // 查询名字等于wangbiao 的
        User user = userMapper.selectOne(wrapper);
        System.out.println(user);
    }

示例3:between  查询xx 到 xx 之间的总数

    public void test(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age",20,30);   // 查询年龄20到30之间的
        Integer i = userMapper.selectCount(wrapper);
        System.out.println(i);
    }

示例4:模糊查询

    @Test
    public void test(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.notLike("name","a");    // 查询名字不包含a 的
        List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
        maps.forEach(System.out::println);
    }
    @Test
    public void test(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.likeRight("name","a")  // 查询包含a 的
                .likeLeft("name","a");  // 左跟 右 就是代表模糊查询时候的% 百分号在左边还是在右边,两个都写代表左右两个% 都有
        List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
        maps.forEach(System.out::println);
    }

示例5:in 查询

  public void test(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.inSql("id","select id from user where age < 21");   // 这里可以写sql,也可以在上一行先查出来,再放到这里当条件
        List<Object> objects = userMapper.selectObjs(wrapper);
        objects.forEach(System.out::println);   // 返回的是id
    }

示例6:orderBy

   @Test
    public void test(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        // 通过id 进行排序
        wrapper.orderByDesc("id");      // 降序,有对应的升序 及其他排序方法
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

代码生成器

确认添加这些依赖:-- 这里少了swagger API 的依赖,到时生成的实体类会导入swagger注解失败报错

     <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

生成代码模板类

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.ArrayList;

// 代码自动生成器
public class ShengChengCode {
    public static void main(String[] args) {
        // 构建一个代码生成器
        AutoGenerator mpg = new AutoGenerator();
        // 配置策略

        // 1、全局配置
        GlobalConfig gconfig = new GlobalConfig();
        String propertyPath = System.getProperty("user.dir");
        gconfig.setOutputDir(propertyPath+"/src/main/java");
        gconfig.setAuthor("wangbiao");
        gconfig.setOpen(false);
        gconfig.setFileOverride(false);     // 是否覆盖
        gconfig.setServiceName("%Service");     // 去Service 的i 前缀
        gconfig.setIdType(IdType.ID_WORKER);
        gconfig.setDateType(DateType.ONLY_DATE);
        gconfig.setSwagger2(true);
        mpg.setGlobalConfig(gconfig);   // set 到自动生成器里

        // 2、设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true");
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);     // set 到自动生成器里

        // 3、包的设置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName("blog");
        pc.setParent("com.biao");
        pc.setEntity("po");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setController("ctrl");
        mpg.setPackageInfo(pc);     // set 到自动生成器里

        // 4、策略配置 --- 这个是最重要的
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("user");                        // 设置要映射的表,可以写多个表,逗号,隔开
        strategy.setNaming(NamingStrategy.underline_to_camel);          // 包的命名规则
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);    // 列的名字规则
        strategy.setEntityLombokModel(true);                // 支持lombok 注解
//        strategy.setLogicDeleteFieldName("deleted");        // 逻辑删除字段
        // 自动填充     创建和修改的字段自动填充
//        TableFill create = new TableFill("create", FieldFill.INSERT);
//        TableFill modified = new TableFill("modified", FieldFill.INSERT_UPDATE);
//        ArrayList<TableFill> list = new ArrayList<>();
//        list.add(gmtCreate);
//        list.add(gmtModified);
//        strategy.setTableFillList(list);
        // 乐观锁配置
//        strategy.setVersionFieldName("version");
//        strategy.setRestControllerStyle(true);
//        strategy.setControllerMappingHyphenStyle(true);

        mpg.setStrategy(strategy);
        // 执行
        mpg.execute();
    }

}

确定数据库和配置,启动这个main 方法即可

 

以上是关于Mybatis-Plus的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis-Plus逆向生成代码

mybatis-plus 代码生成

mybatis-plus代码生成器代码

详解:MyBatis-Plus 代码生成器的使用

详解:MyBatis-Plus 代码生成器的使用

详解:MyBatis-Plus 代码生成器的使用