MybatisPlus

MyBatisPlus

MP是基于mybatis基础上开发的增强型工具,维勒简化mybatis开发,提高效率

因为企业中最常用的是SpringBoot所以我们主要研究基于SpringBoot使用Mybatis

快速入门

首先创建boot项目,你发现没有MP对应的启动依赖,于是我们要自己配,选好mysql的,点击完成(注意第一件事是更改Maven路径)

手动导入必要依赖

<!--        添加MyBatisPlus依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
                <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>

随后配置好数据源

image-20220515202409544

接着写好domain(get,set,tostring)

image-20220515202557590

接着就可以完成dao接口层了

之前springboot项目我们写dao接口是要自己去写里面的抽象方法再在接口上用@Mapper声明,现在用了MP之后我们只用继承BaseMapper并且传入对应实体类,再用@Mapper声明就可以进行测试了

@Mapper
public interface UserDao extends BaseMapper<User> {


}
@SpringBootTest
class MyBatisPlusQuickstarApplicationTests {
    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll() {
        List<User> userList = userDao.selectList(null);
        System.out.println(userList);
    }

}

这直接可以返回所有数据(注意这里只有单表才可以多表要进行配置)

MyBatisPlus介绍

详细接受和教程直接看官网https://baomidou.com/,这是国人写的而且教程适合新手,建议看完

标准数据层开发

image-20220515215618059

在以上快速入门的基础上来测试MP自带的接口(注意在不配置具体表的情况下单表的数据库才能直接测)

@SpringBootTest
class MyBatisPlusQuickstarApplicationTests {
    @Autowired
    private UserDao userDao;


    @Test
    void testSave(){
        User user=new User();
        user.setUsername("zhangsan");
        user.setEmail("sb123@163.com");
        user.setPassword("sbsbsb");
        int insert = userDao.insert(user);
        System.out.println(insert);
    }
    @Test
    void testDelete(){
        userDao.deleteById(4);
    }
    @Test
    void testUpdate(){
        User user=new User();
        user.setId(6);
        user.setUsername("老六");
        int i = userDao.updateById(user);
        System.out.println(i);
    }
    @Test
    void testGeiById(){
        User user = userDao.selectById(6);
        System.out.println(user);
    }
        }

补充个简化实体类开发的依赖lombok(小辣椒)

首先导入依赖(因为是springboot项目版本号就不写了)

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
	<scope>provided</scope>
</dependency>
//用lombok创建实体类,就只用自己声明属性就可以了
@Setter
@Getter
@ToString
public class User {
private int id;
private String username;
private String email;
private String password;

还有的相关注解

@Setter
@Getter
@ToString
@NoArgsConstructor//无参构造方法
@AllArgsConstructor//有参构造方法
@EqualsAndHashCode//equals方法

@Date最常用相当于以上全部注解

image-20220516143918825

标准分页功能制作

首先我们要开启mp这个功能就要到拦截器中添加分页的拦截器

image-20220516150133986

接着就可以测试其自带的分页接口了

//    测试分页功能接口
    @Test
    void testGetByPage(){
        IPage page=new Page(1,2);
        userDao.selectPage(page,null);
        System.out.println("当前页码值;"+page.getCurrent());
        System.out.println("每页显示数;"+page.getSize());
        System.out.println("总页数;"+page.getPages());
        System.out.println("总条数;"+page.getTotal());
        System.out.println("数据;"+page.getRecords());
    }

image-20220516150231220

这里要看底层实现可以到方法中去看也可以开启mp的日志

开启方式如下

到我们的yml配置文件中配置

#    开启mp的日志(输出到控制台的日志)
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

要开启其他方式的日志需要其他的配置(一般做测试将日志关了,遇到问题才打开)

条件查询

条件查询三种格式

首先日志文件较多导致我们不容易直接看到结果,我们现在配置文件中简化下日志的显示

image-20220516152155451

方式一:

@Test
void testGetAll() {
    //按条件查询
    QueryWrapper qw=new QueryWrapper();//wrapper接口实现查询的实现类
    //添加条件
    qw.lt("id",3);//id小于3的所有数据
    List<User> userList = userDao.selectList(qw);
    System.out.println(userList);
}

image-20220516153039439

方式二:lambda格式的条件查询

//        方式二:lambda格式的条件查询(要在实现类中用泛型指定数据库对应的实体类)
        QueryWrapper<User> qw=new QueryWrapper<User>();
        qw.lambda().lt(User::getId,4);
        List<User> userList = userDao.selectList(qw);
        System.out.println(userList);

方式三:用LambdaQueryWrapper实现类简化方式二

//        方式三,简化方式二
        LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<User>();
        lqw.lt(User::getId,3);
        List<User> userList = userDao.selectList(qw);
        System.out.println(userList);

多条件查询直接加条件就好了

//        多条件查询id在1-3之间的数据
        LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<User>();
        //lqw.lt(User::getId,3);
       //lqw.gt(User::getId,1);
		lqw.lt(User::getId,3).gt(User::getId,1);
//and多条件直接写成这种链式语句
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

    }
//        多条件查询id在2-3之外的数据
        LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<User>();
        lqw.lt(User::getId,2).or().gt(User::getId,3);
//or()
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

条件查询null值处理

原始方法用if判断条件是否为空(不推荐,会导致代码出现多个if语句)

image-20220516155405287

推荐使用条件控制参数的方式

只有前面的条件判断为true,后面的语句才有效

image-20220516155653981

查询投影

设置查询结果的样式

就是设置要显示的列

image-20220516160304436

查询条件

image-20220516160555351

主要就是一些方法的使用

image-20220516161127753

image-20220516161221804

其余的方法去看官文

条件构造器 | MyBatis-Plus (baomidou.com)

映射匹配兼容性

当表列名和我们实体类的列名不一致的时候

image-20220516162904214

编码中添加了数据库中没有定义的属性

image-20220516163101893

采用默认查询开放了所有字段的查看权限(包括密码这种不能显示的数据,只用返回的json里面有就能被想办法获取)

image-20220516163341111

表名和实体类名字不对应(这样mp不知道我们到底要查哪张表,这就是之前我们说的只能查单表的数据库)

在实体类上用@TableName绑定对应的表名

image-20220516163537586

一个数据库中所有的表中都有相同的前缀,我们也可以直接配置全局配置,将所有的实体类前缀都加上,这里假设所有表的前缀都是tb_

db-config:
  table-prefix: tb_

这样就不用在实体类上使用@TableName注解了

id生成策略(主键生成)

全部策略请看官文

主键策略 | MyBatis-Plus (baomidou.com)

默认策略auto

image-20220516164306296

image-20220516164734706

我们一般到配置文件中直接更改默认的策略

db-config:
  id-type: assign_id

多数据操作(删除&查询)

image-20220516165925340

逻辑删除

image-20220516170235048

image-20220516170935998

image-20220516171009227

建议使用全局配置逻辑字段

image-20220516171114114

一代配置了逻辑查询,则用mp的删除操作就变成了update操作,只是将对应的逻辑字段变成已删除标记

mp的查询所有也变成只查询逻辑字段是未删除的数据

要想查全部只有自己写sql语句进行查询

乐观锁

之前jdbc,和web开发也讲过,遇到并发现象带来的资源同时抢占问题,我们就要给资源上锁,免得同一个资源被多线程抢占

MP中通过拦截器可以实现乐观锁(只能解决中小型线程出现的问题)

一个乐观锁开发如下

version让同一个资源只能让一个线程操作,操作时拿到数据对应version,使其加1,其他线程也相对这个数据进行操作的时候发现version和数据提供的version对不上,则不能完成操作

image-20220516205017345

image-20220516205259026

image-20220516205318562

image-20220516205413515

代码生成器(了解)

image-20220516205949032

首先创建好boot项目,导入所需依赖,以下是需要手动导入的

      <!--        添加MyBatisPlus依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
<!--        代码生成器-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
<!--velocity模板引擎,使用其提供的模板-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>

image-20220516212425770

运行你发现弹出了生成好的目录

image-20220516212510685

里面的文件是根据数据库实现的,但是生成位置是默认位置,我们可以创建个管理类去更改其配置

image-20220516212633518

一般配置所需代码如下

package com.ember;

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;

public class CodeGenerator {
    public static void main(String[] args) {
        //1.获取代码生成器的对象
        AutoGenerator autoGenerator = new AutoGenerator();

        //设置数据库相关配置
        DataSourceConfig dataSource = new DataSourceConfig();
        dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        autoGenerator.setDataSource(dataSource);

        //设置全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setOutputDir(System.getProperty("user.dir")+"/mybatisplus_04_generator/src/main/java");    //设置代码生成位置
        globalConfig.setOpen(false);    //设置生成完毕后是否打开生成代码所在的目录
        globalConfig.setAuthor("黑马程序员");    //设置作者
        globalConfig.setFileOverride(true);     //设置是否覆盖原始生成的文件
        globalConfig.setMapperName("%sDao");    //设置数据层接口名,%s为占位符,指代模块名称
        globalConfig.setIdType(IdType.ASSIGN_ID);   //设置Id生成策略
        autoGenerator.setGlobalConfig(globalConfig);

        //设置包名相关配置
        PackageConfig packageInfo = new PackageConfig();
        packageInfo.setParent("com.aaa");   //设置生成的包名,与代码所在位置不冲突,二者叠加组成完整路径
        packageInfo.setEntity("domain");    //设置实体类包名
        packageInfo.setMapper("dao");   //设置数据层包名
        autoGenerator.setPackageInfo(packageInfo);

        //策略设置
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setInclude("tbl_user");  //设置当前参与生成的表名,参数为可变参数
        strategyConfig.setTablePrefix("tbl_");  //设置数据库表的前缀名称,模块名 = 数据库表名 - 前缀名  例如: User = tbl_user - tbl_
        strategyConfig.setRestControllerStyle(true);    //设置是否启用Rest风格
        strategyConfig.setVersionFieldName("version");  //设置乐观锁字段名
        strategyConfig.setLogicDeleteFieldName("deleted");  //设置逻辑删除字段名
        strategyConfig.setEntityLombokModel(true);  //设置是否启用lombok
        autoGenerator.setStrategy(strategyConfig);
        //2.执行生成操作
        autoGenerator.execute();
    }
}

根据需求配置好了就运行就好了

posted @ 2022-05-17 20:44  Ember00  阅读(62)  评论(0)    收藏  举报