Mybatis 特别篇 Mybatis-plus入门教程

10 篇文章 0 订阅
9 篇文章 0 订阅


前言

学习之前,需要有SSM基础比较好,Mybatis可以节省我们大量的sql代码编写的时间,尤其在简单的sql语句中只需要调用一个方法即可完成增删改查


![在这里插入图片描述](https://img-blog.csdnimg.cn/e06f79d0c29b497dbde8c3575c3f56fb.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LiN5aSq5oeC57yW56iL,size_20,color_FFFFFF,t_70,g_se,x_16)

正如官方所介绍为简化开发而生
在这里插入图片描述

一、MybatisPuls有什么特点

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
    内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
    内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
    内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

支持数据库

任何能使用 mybatis 进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下,如果不在下列表查看分页部分教程 PR 您的支持。

mysql,oracle,db2,h2,hsql,sqlite,postgresql,sqlserver,Phoenix,Gauss ,clickhouse,Sybase,OceanBase,Firebird,cubrid,goldilocks,csiidb

二、使用步骤

1.快速入门(官网案例)

参考地址

  1. 创建数据库和user表
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');
  1. 使用IDEA创建工程 官网默认用h2数据库我们不需要进行导入
<!--数据库驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis-plus不用在导入mybatis了-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.0.5</version>
</dependency>
  1. 配置数据源
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatisplus?useSSL=false&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
  1. 开始编码
  • 传统mybatis写法依然支持不做介绍,可参考mybatis原生案例
  • 使用mybatis-plus (pojo->mapper接口->使用)我们可以看到都不需要配置xml文件
    创建User实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

创建Mapper接口

//在对应的Mapper上面是实现基本的接口BaseMapper
@Repository
public interface UserMapper extends BaseMapper<User> {
//所有的crud的擦欧总已经编写完毕了
}

简单看看baseMapper里面已经定义好啦非常多的接口
在这里插入图片描述
入口文件增加注解扫描Mapper
@MapperScan("cn.qileyun.mybatisplus.mapper")
测试一下看看

//继承baseMapper所有可以使用它的所有方法,里面已经封装好了基本crud代码
@Autowired
private UserMapper userMapper;


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

在这里插入图片描述

2. 配置日志输出

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

在这里插入图片描述

3. MybatisPlus中的雪花算法

User user = new User();
user.setName("我爱学编程");
user.setAge(3);
user.setEmail("1541177517@qq.com");
int result = userMapper.insert(user);//帮我们自动生成id
System.out.println(result);
System.out.println(user);

我们并没有插入id,当是给我们生成一个全局唯一id,我们来探究一下
在这里插入图片描述
在这里插入图片描述

4. 自定义ID生成策略

在pojo类中定义id

  • AUTO 自增 数据库id必须是自增的
  • UUID uuid全球唯一id
  • INPUT 手动输入需要自己配置id
  • ID_WORKER_STR 数字->字符串
  • INONE 不使用id生成
  • ID_WORKER 默认全局唯一id 雪花算法
    @TableId(type = IdType.AUTO)//自增 数据库id必须是自增的
    private Long id;

5. 自动填充

  1. 修改数据库
    在这里插入图片描述
  2. 修改实体类
// 字段填充内容
@TableField(fill = FieldFill.INSERT)
 private Date createTime;
 @TableField(fill = FieldFill.INSERT_UPDATE)
 private Date updateTime;
  1. 编写处理器
@Slf4j
@Component//加入到ico容器中
public class MyMetaObjectHandler implements MetaObjectHandler {
    //插入时的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
    //更新时的填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}
  1. 执行插入和修改
    在这里插入图片描述

6. 乐观锁

  • 乐观锁:顾名思义十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题,在次更新值测试

  • 悲观锁:顾名思义十分悲观,无论干什么都会上锁!再去操作!

  • 取出记录时,获取当前version

  • 更新时,带上version

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

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

--A
update user set name = "lala",version = version+1 where id=2 and version = 1
--B 如果现在B先抢占了线程,就会导致A修改失败,因为version字段已经+1操作变成了2了
update user set name = "lala",version = version+1 where id=2 and version = 1

使用乐观锁插件

  1. 增加字段
    在这里插入图片描述
  2. 实体类添加字段
@Version
private  Integer version;
  1. 注册组件
//扫描我们的mapper文件夹
@MapperScan("cn.qileyun.mybatisplus.mapper")
@EnableTransactionManagement
@Configuration//配置类
public class MybatisPlusConfig {
    //注册乐观锁插件 这个按照你的mybatis二选一
      /**
     * 旧版
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
    
    /**
     * 新版
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

  1. 测试看看
    //    测试成功的案例
    @Test
    public void testOptimisticLocker() {
        //1. 查询用户信息
        User user = userMapper.selectById(1L);
        //2.修改用户信息
        user.setName("zengfeiixang");
        user.setEmail("1541177517@qq.com");
        //3. 执行更新操作
        userMapper.updateById(user);
    }

    //   测试失败的案例
    @Test
    public void testOptimisticLocker2() {
        //1. 查询用户信息
        User user = userMapper.selectById(1L);
        //2.修改用户信息
        user.setName("bbbbb");
        user.setEmail("1541177517@qq.com");
        //模拟另外一个线程执行插队操作
        User user2 = userMapper.selectById(1L);
        user2.setName("aaaaaa");
        user2.setEmail("1541177517@qq.com");

        //3. 执行更新操作
        userMapper.updateById(user2);//执行成功
        userMapper.updateById(user);//更改失败如果没有乐观锁就会覆盖插队线程的值
    }

在这里插入图片描述

7. 查询

基本查询

//测试查询
  @Test
  public void testSelectById(){
      //查询单个
      User user = userMapper.selectById(1L);
      System.out.println(user);
  }
  //测试批量查询
  @Test
  public void testSelectByBatchId(){
      List<User> users = userMapper.selectBatchIds(Arrays.asList(1,2,3));
      users.forEach(System.out::println);
  }
  //条件查询 map
  @Test
  public void testSelectByBatchIds(){
      HashMap<String, Object> map = new HashMap<>();
      //自定义查询
      map.put("name","Tom");
      map.put("age",28);
      List<User> users = userMapper.selectByMap(map);
      users.forEach(System.out::println);
  }

分页查询

分页在网站使用的十分之多
1、原始的limit进行分页
2、pageHelper 第三方插件
3、MP其实内置了分页插件
使用教程

  1. 注册插件
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
    PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
    return paginationInterceptor;
}

/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 新版本好像用这个了没有测试 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
	  MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
	  interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
	  return interceptor;
}
  1. 测试一下
//测试分页查询
public void testPage(){
    //参数1 第一页
    //参数2 一页条目数量
    IPage<User> page = new Page<>(1,5);
    IPage<User> userIPage = userMapper.selectPage(page, null);
    userIPage.getRecords().forEach(System.out::println);
    System.out.println(page.getTotal());//总计
}

8. 删除

普通删除

//测试删除
@Test
public void testDeleteById(){
    userMapper.deleteById(1468132628929495041L);
}

//批量删除
@Test
public void testDeleteBatchId(){
    userMapper.deleteBatchIds(Arrays.asList(1468132628929495041L,1468132628929495042L));
}

//通过Map删除
public void testDeleteMap(){
    HashMap<String, Object> map = new HashMap<>();
    map.put("name","lala");
    userMapper.deleteByMap(map);
}

逻辑删除

物理删除:从数据库中直接移除
逻辑删除:在数据库中没有移除,而是通过一个变量来让他失效!delete =0 => delete=1
可以把他看成一个回收站一样,只是给他标识一个已经不存在了

  1. 数据库增加字段
    增加int类型的delete字段并且默认值为0
    在这里插入图片描述

  2. 实体类增加字段

@TableLogic
private Integer deleted;
  1. 编写配置
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)
  1. 注册插件
//逻辑删除
@Bean
public ISqlInjector sqlInjector(){
    return new LogicSqlInjector();
}
  1. 测试删除代码
    其实执行的不在是delete操作了而是更新了字段吧deleted = 1
    在这里插入图片描述
    查询看看可以看出已经自动加上了deleted = 0的条件,判断是否被删除过
    在这里插入图片描述

9. 性能分析插件(好像新版被移除了)

MP提供了性能分析插件,如果超过这个时间就停止运行!

  1. 导入插件
 //sql执行效率插件
    @Bean
    @Profile({"dev","test"})//设置dev test环境开启,保证我们的效率
    public PerformanceInterceptor performanceInterceptor(){
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(100);//设置sql执行的最大时间,如果超超过了就不执行
        performanceInterceptor.setFormat(true);//sql格式化
        return new PerformanceInterceptor();
    }
  1. 配置spring为开发环境
spring:
  profiles:
    active: dev
  1. 测试使用
    如果这个时间超过100ms就会报错
    在这里插入图片描述

9. 条件构造器

可以看出官方有非常多的条件
在这里插入图片描述

判断条件

@Test
 void contextLoads() {
     //查询name不为空的用户,年龄大于等于12,并且邮箱不为空
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.isNotNull("name").isNotNull("email").ge("age",12);
     userMapper.selectList(wrapper).forEach(System.out::println);
 }

 @Test
 void test2(){
     //查询名字lala
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.eq("name","lala");
     //selectOne 查询一个数据
     System.out.println(userMapper.selectOne(wrapper));
 }
 //查询 10 到 20 岁的用户数
@Test
void test3(){
    QueryWrapper<User> wrapper=new QueryWrapper<>();
    wrapper.between("age",10,20);Integer count = userMapper.selectCount(wrapper);
    //查询 10 到 20 岁的用户的结果数System.out.println(count);
}

使用 like + notLike + likeRight

@Test
void selectLike01(){
    QueryWrapper<User> wrapper=new QueryWrapper<>();
    wrapper
            .notLike("name","To") //名字不包含 To
            .like("name","o") //名字包含 o 的
            //左和右 左:%e   右:e%  两边:%e%
            //右查询
            .likeRight("email","test");List<Map<String, Object>> users = userMapper.selectMaps(wrapper);
    users.forEach(System.out::println);
}

子查询

@Test
void selectLike02(){
    QueryWrapper<User> wrapper=new QueryWrapper<>();
    wrapper
            //一个SQL语句写的子查询
            .inSql("id","select id from user where age<20");List<Object> users = userMapper.selectObjs(wrapper);
    users.forEach(System.out::println);
}

降序查询

@Test
void selectLike03(){
    QueryWrapper<User> wrapper=new QueryWrapper<>();
    //降序排序
    wrapper.orderByDesc("id");
    //升序排序
    //wrapper.orderByAsc("id");List<User> users = userMapper.selectList(wrapper);
    users.forEach(System.out::println);
}

更多的可以参考官方文档

10. 代码生成器

  1. 添加依赖
<!--代码生成器-->
<dependency>
   <groupId>com.baomidou</groupId>
   <artifactId>mybatis-plus-generator</artifactId>
   <version>3.0.7</version>
</dependency>
<!--模版 -->
<dependency>
   <groupId>org.apache.velocity</groupId>
   <artifactId>velocity</artifactId>
   <version>1.7</version>
</dependency>
  1. 测试类编写生成代码类
//需要构建一个代码生成器对象
 AutoGenerator mpg = new AutoGenerator();
 //全局配置
 GlobalConfig gc = new GlobalConfig();
 String property = System.getProperty("user.dir");
 gc.setOutputDir(property+"/src/main/java");
 gc.setAuthor("奇乐云");
 gc.setOpen(false);
 gc.setFileOverride(false);//是否覆盖
 gc.setServiceImplName("%sService");//去除Service的I前缀
 gc.setIdType(IdType.ID_WORKER);
 gc.setDateType(DateType.ONLY_DATE);
 gc.setSwagger2(true);
 mpg.setGlobalConfig(gc);

 //设置数据源
 DataSourceConfig dsc= new DataSourceConfig();
 dsc.setUrl("jdbc:mysql://localhost:3306/mybatisplus?useSSL=false&useUnicode=true&characterEncoding=utf-8");
 dsc.setDriverName("com.mysql.cj.jdbc.Driver");
 dsc.setUsername("root");
 dsc.setPassword("123456");
 dsc.setDbType(DbType.MYSQL);
 mpg.setDataSource(dsc);
 //包的配置
 PackageConfig pc = new PackageConfig();
 //pc.setModuleName("blog");//模块
 pc.setParent("cn.qileyun.mybatisplus");//包根路径
 pc.setEntity("entity");
 pc.setMapper("mapper");
 pc.setService("service");
 pc.setController("controller");
 mpg.setPackageInfo(pc);

 //策略配置
 StrategyConfig strategy = new StrategyConfig();
 strategy.setInclude("user");//设置要映射的表 可以传入多个表
 strategy.setNaming(NamingStrategy.underline_to_camel);
 strategy.setEntityLombokModel(true);//自动lombok
 strategy.setRestControllerStyle(true);
 strategy.setLogicDeleteFieldName("deleted");//逻辑删除字段
 //自动填充配置
 TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
 TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);
 ArrayList<TableFill> tableFills = new ArrayList<>();
 tableFills.add(gmtCreate);
 tableFills.add(gmtModified);
 strategy.setTableFillList(tableFills);
 //乐观锁
 strategy.setVersionFieldName("version");

 strategy.setRestControllerStyle(true);
 strategy.setControllerMappingHyphenStyle(true);//
 mpg.setStrategy(strategy);

 mpg.execute();//执行策略

看到一个写的不错的代码生成器

package com.yixin;
 
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
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 org.junit.platform.commons.util.StringUtils;
 
import java.util.ArrayList;
import java.util.Scanner;
 
public class CodeGenerator {
 
 
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotBlank(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }
 
 
 
 
 
    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
 
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");//设置代码生成路径
        gc.setFileOverride(true);//是否覆盖以前文件
        gc.setOpen(false);//是否打开生成目录
        gc.setAuthor("yixin");//设置项目作者名称
        gc.setIdType(IdType.AUTO);//设置主键策略
        gc.setBaseResultMap(true);//生成基本ResultMap
        gc.setBaseColumnList(true);//生成基本ColumnList
        gc.setServiceName("%sService");//去掉服务默认前缀
        gc.setDateType(DateType.ONLY_DATE);//设置时间类型
        mpg.setGlobalConfig(gc);
 
        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123456");
        mpg.setDataSource(dsc);
 
        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent("com.yixin");
        pc.setMapper("mapper");
        pc.setXml("mapper.xml");
        pc.setEntity("pojo");
        pc.setService("service");
        pc.setServiceImpl("service.impl");
        pc.setController("controller");
        mpg.setPackageInfo(pc);
 
        // 策略配置
        StrategyConfig sc = new StrategyConfig();
        sc.setNaming(NamingStrategy.underline_to_camel);
        sc.setColumnNaming(NamingStrategy.underline_to_camel);
        sc.setEntityLombokModel(true);//自动lombok
        sc.setRestControllerStyle(true);
        sc.setControllerMappingHyphenStyle(true);
 
        sc.setLogicDeleteFieldName("deleted");//设置逻辑删除
 
        //设置自动填充配置
        TableFill gmt_create = new TableFill("create_time", FieldFill.INSERT);
        TableFill gmt_modified = new TableFill("update_time", FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills=new ArrayList<>();
        tableFills.add(gmt_create);
        tableFills.add(gmt_modified);
        sc.setTableFillList(tableFills);
 
        //乐观锁
        sc.setVersionFieldName("version");
        sc.setRestControllerStyle(true);//驼峰命名
 
 
 
      //  sc.setTablePrefix("tbl_"); 设置表名前缀
        sc.setInclude(scanner("表名,多个英文逗号分割").split(","));
        mpg.setStrategy(sc);
 
        // 生成代码
        mpg.execute();
    }
 
}
  1. 测试看看
    在这里插入图片描述
    其他参数可以参考官网进行配置,新版本做了很多更新。

总结

这里是看了狂神说的mybatis plus的入门教程,但是看了官网最新的mybatis plus貌似改了蛮多东西的,有机会多看看官网教程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值