MyBatisPlus入门

目录

概述

SpringBoot继承MyBatisPlus

CRUD

        新增

        删除

        修改

        查询

条件构造器

全局配置

相关注解

ActiveRecord

插件

分页插件

防止全表删除插件

乐观锁插件

        乐观锁插件的使用

逻辑删除

使用逻辑删除

扩展

        自动填充

        Sql注入器

        代码生成器Generator

        代码生成器MyBatisX


 

部分图片来自百战程序员

概述

MyBatis-Plus(简称 MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。

MyBatisPlus的愿景是成为MyBatis最好的搭档,就像魂斗罗中的1P、2P,基友搭配,效率翻倍。

官方网址: MyBatis-Plus

 

SpringBoot继承MyBatisPlus

1、引入MyBatisPlus的依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>
<!-- MyBatisPlus -->
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <version>3.5.0</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.26</version>
</dependency>
<!-- lombok -->
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <optional>true</optional>
</dependency>

2、在yml文件中创建数据源

# 数据源
spring:
  datasource:
   driver-class-name: com.mysql.cj.jdbc.Driver
   url: jdbc:mysql:///school?serverTimezone=UTC
   username: root
   password: root

3、创建pojo类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
  private Integer id;
  private String name;
  private String email;
  private String gender;
  private Integer age;
}

4、创建mapper接口,继承BaseMapper,泛型为相关的pojo类

public interface StudentMapper extends BaseMapper<Student> {
}

5、在SpringBoot启动类中添加@MapperScan注解,扫描Mapper文件夹

@SpringBootApplication
@MapperScan("com.itbaizhan.mpdemo2.mapper")
public class SpringbootMpApplication {
  public static void main(String[] args) {
    SpringApplication.run(SpringbootMpApplication.class, args);
   }
}

6、测试Mapper方法

@SpringBootTest
public class StudentMapperTest {
  @Autowired
  private StudentMapper studentMapper;


  @Test
  public void testFindById(){
    Student student = studentMapper.selectById(1);
    System.out.println(student);
   }
}

 

 

CRUD

在MyBatisPlus中只需要持久层接口继承BaseMapper,并且泛型为相关pojo类,那么MyBatisPlus将会自动帮你创建相关的增删改查方法

        新增

insert方法作用为添加

  1. yml配置文件开启SQL日志打印
    # 开启SQL日志
    mybatis-plus:
      configuration:
       log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  2. 测试添加方法:
    @Test
    public void testAdd(){
      Student student = new Student(null,"baizhan","bz@bz.com","m",20);
      studentMapper.insert(student);
      // MyBatisPlus插入成功后,可直接直接获取主键的值
      System.out.println(student.getId());
    }

 

        删除

deleteById方法的作用是根据ID删除数据

deleteBatchIds方法的作用是批量删除

deleteByMap方法的作用是根据字段条件删除键为数据库列名

@Test
    public void testDelete(){
        studentMapper.deleteById(7);
    }

 

 

 

@Test
    public void testDeleteBatch(){
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        studentMapper.deleteBatchIds(list);
    }

 

 

@Test
    public void testDeleteByMap(){
        Map<String,Object> map = new HashMap<>();
        map.put("address","北京");
        studentMapper.deleteByMap(map);
    }

删除前: 

 删除后:

 

        修改

update方法作用为修改

updateById方法作用为根据Id修改

 

@Test
    public void testUpdate(){
        Student student = new Student(3,"张三","男","哈尔滨");
        studentMapper.updateById(student);

    }

修改前:

修改后:

 

        查询

selectById方法的作用是根据Id查询

selectBatchIds方法的作用是根据id批量查询

selectByMap方法的作用是根据字段条件查询

 

数据库:

 

 

@Test
    public void testSelectById(){
        Student student = studentMapper.selectById(1);
        System.out.println(student);
    }

 

 

@Test
    public void testSelectBatchIds(){
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        List<Student> students = studentMapper.selectBatchIds(list);
        students.forEach(System.out::println);
    }

 

 @Test
    public void testSelectByMap(){
        Map<String,Object> map = new HashMap<>();
        map.put("sex","男");
        List<Student> students = studentMapper.selectByMap(map);
        students.forEach(System.out::println);
    }

 

条件构造器

Mybatis-Plus通过QueryWrapper对象让用户自由的构建SQL条件,简单便捷,没有额外的负担,能够有效提高开发效率。

1QueryWrapper对象构造了Sql条件过后,传递给selectList()方法即可查询

2QueryWrapper构造的Sql条件之间默认为and连接

 

条件参数说明:

查询方式

说明

or

或条件语句

and

且条件语句

like

模糊查询 like

notLike

模糊查询 not Like

exists

exists 条件语句

notExists

not Exists 条件语句

isNull

null 值查询

isNotNull

is Not Null 查询

in

in 查询

notIn

not in 查询

groupBy

分组查询

orderBy

排序查询

having

分组后筛选

eq

等于 =

ne

不等于 <>

between

between 条件语句

gt

大于>

ge

大于等于>=

lt

小于<

le

小于等于<=

 

 

@Test
    public void testQueryWrapper(){
        QueryWrapper<Student> wrapper = new QueryWrapper<>();
        wrapper.lt("id",5).gt("id",1);
        List<Student> students = studentMapper.selectList(wrapper);
        students.forEach(System.out::println);
    }

 

全局配置

假如数据库的所有表都以tb_开头,主键都是自增的。如果针对每一个实体类都要添加相关注解比较麻烦,可以在SpringBoot配置文件中进行全局配置,该配置在所有的实体类中都生效。

mybatis-plus:

 # 全局配置

  global-config:

   db-config:

   #主键类型

    id-type: AUTO

   # 设置表名前缀

    table-prefix: tb_

   # 是否使用驼峰转下划线命名,默认开启

    table-underline: true

 

相关注解

我们将表名改为tb_student,id字段名改为sid,name字段名改为sname,此时由于名字不同无法完成映射,我们可以通过相关注解为实体类对象指定表名和列名。

@TableName

作用:指定类为哪个表的实体类

位置:类上方

 

@TableId

作用:指定实体类的属性为主键

位置:属性上方

属性:

  • value:主键字段名
  • type:主键策略

描述

NONE

无状态,不设置主键类型

AUTO

自增主键

INPUT

插入前自行设置主键值

ASSIGN_ID

默认策略,使用雪花算法自动生成主键ID,主键类型为整形或字符串。(雪花算法:微博开源的分布式ID生成算法,使用一个64位的Long类型数字作为全局唯一ID。在分布式系统中的应用十分广泛,且ID引入了时间戳,基本上保持自增)

ASSIGN_UUID

自动生成排除中划线的UUID作为主键,主键类型为字符串。

 

@TableField

作用:在属性和列名不同的情况下,指定映射关系

位置:非主键属性上方

@Data

@NoArgsConstructor

@AllArgsConstructor

@TableName("tb_student")

public class Student{

  @TableId(value="sid",type=IdType.AUTO)

  private Integer id;

  @TableField("sname")

  private String name;

  private String email;

  private String gender;

  private Integer age;

}

 

ActiveRecord

Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。

在MyBatisPlus中,AR模式即在实体类中封装了对数据库的访问而不通过mapper类。

用法:

1、虽然操作数据库不通过mapper类,但需要编写mapper类并继承BaseMapper

public interface StudentMapper extends BaseMapper<Student>{
}

2、实体类继承Model类,开启AR模式

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student extends Model<Student> {
    private Integer id;
    private String name;
    private String sex;
    private String address;
}

3、接下来就可以测试了

@SpringBootTest
public class StudentTest {

    @Test
    public void testFindAll(){
        Student student = new Student();
        List<Student> students = student.selectAll();
        students.forEach(System.out::println);
    }
}

 

 

// AR新增
@Test
public void testAdd(){
  Student student = new Student(10, "baizhan", "bz@bz.com", "m", 20);
  student.insert();
}


// AR修改
@Test
public void testUpDate(){
  // 创建实体类对象
  Student student = new Student();
  // 设置需要更新的属性
  student.setName("baby");
  // 设置需要修改的id
  student.setId(10);
  // 根据主键进行更新,没有设置的值忽略
  student.updateById();
}


// AR根据id查询
@Test
public void testFindById(){
  Student student = new Student();
  student.setId(10);
  Student student1 = student.selectById();
  System.out.println(student1);
}


// AR删除
@Test
public void testDeleteById(){
  Student student = new Student();
  student.setId(10);
  student.deleteById();
}


// AR查询所有
@Test
public void testFindAll(){
  Student student = new Student();
  List<Student> students = student.selectAll();
  students.forEach(System.out::println);
}

 

插件

MyBatis插件机制

MyBatis插件就是对Executor、StatementHandler、ParameterHandler、ResultSetHandler这四个接口上的方法进行拦截,利用JDK动态代理机制,为这些接口的实现类创建代理对象,在执行方法时,先去执行代理对象的方法,从而执行自己编写的拦截逻辑。

 

  • Executor
    MyBatis的内部执行器,它负责调用StatementHandler操作数据库,并把结果集通过 ResultSetHandler进行自动映射。
  • StatementHandler
    MyBatis直接让数据库执行sql脚本的对象。
  • ParameterHandler
    MyBatis实现Sql入参设置的对象。
  • ResultSetHandler
    MyBatis把ResultSet集合映射成POJO的接口对象。

 

MyBatisPlus常用插件

MyBatisPlus依据MyBatis插件机制,为我们提供了一些开发中常用的插件,我们在开发中使用即可。

常用插件:

  • 自动分页: PaginationInnerInterceptor
  • 防止全表更新与删除: BlockAttackInnerInterceptor
  • 乐观锁: OptimisticLockerInnerInterceptor

这些插件都实现了InnerInterceptor接口

 

分页插件

在配置类或启动类配置分页插件:


// 注册插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
  MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
  return interceptor;
}

 使用:

AR模式分页查询

 @Test
    public void testPage(){
        //创建分页条件
        Page page = new Page(0,2);
        //查询构造器
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.lt("id",10).gt("id",0);

        Student student = new Student();
        IPage<Student> iPage = student.selectPage(page,queryWrapper);
        List<Student> records = iPage.getRecords();
        records.forEach(System.out::println);
    }

 

 

防止全表删除插件

作用:分析删除/更新语句,防止小白或者恶意进行删除/更新全表操作。

注意:

  • 该插件只支持 MySQL5.6.3 以上版本
  • 该插件只建议在开发环境中使用,不建议在生产环境使用

插件使用:

 

1、在配置类或启动类配置防止全表更新与删除插件

// 注册插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
  MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  // 分页插件
  interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
  // 防止全表更新与删除插件
  interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
  return interceptor;
}

2、测试全表删除

// AR删除所有
@Test
public void testDeleteAll() {
  Student student = new Student();

//当条件构造器没有条件,代表删除所有数据

 student.delete(new QueryWrapper());
}

 

乐观锁插件

 

修改数据库中的数据时,为了避免同时被其他人修改,最好的办法就是对该数据进行加锁以防止并发。

锁的设计分为悲观锁和乐观锁:

  • 悲观锁:悲观锁对数据被外界修改持保守态度。即在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现往往依靠数据库提供的锁机制。

  • 乐观锁:乐观锁在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。

MyBatisPlus乐观锁插件实现方式:

  1. 取出记录时,获取当前version
  2. 更新时,带上这个version
  3. 执行更新时, set version = newVersion where version = oldVersion
  4. 如果version不对,就更新失败

 

        乐观锁插件的使用

使用MyBatisPlus乐观锁插件:

1、在表中添加version列,且默认值为0

2pojo类中添加version属性,并在属性上方添加@Version属性

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student extends Model<Student> {
    private Integer id;
    private String name;
    private String sex;
    private String address;

    @Version
    private int version;
}

测试修改功能

@Test
    public void testVersion(){
        Student student = new Student();
        student.setId(1);
        student.setName("索隆");

        student.setVersion(10);
        student.updateById();

    }

通过输出的Sql语句可以发现,mybatisPlus在修改语句的后面添加了一个version条件,此时version为10,那么就根本不会修改数据库中路飞的名字 

 

逻辑删除

在实际开发中,由于数据十分重要,为了避免误删除数据导致数据无法找回,我们往往不会使用物理删除,即从数据库中直接删除数据。而是采用逻辑删除的方式,即不会真正在数据库删除数据,而是通过一个变量代表它被删除

 

deleted属性代表该数据是否删除,0代表未删除,1代表已删除。此时增删改查的Sql语句发生变化:

  • 插入: 不作限制
  • 查找: 追加where条件过滤掉已删除数据。
  • 更新: 追加where条件防止更新到已删除数据。
  • 删除: 转变为更新

 

例如:

  • 删除: update user set deleted=1 where id = 1 and deleted=0
  • 查找: select id,name,deleted from user where deleted=0

使用逻辑删除

  1. 在配置文件配置逻辑删除
    # mybatis-plus相关配置
    mybatis-plus:
     # 全局配置
      global-config:
       db-config:
       # 全局逻辑删除的字段名
        logic-delete-field: deleted
       # 逻辑已删除值(默认为 1)
        logic-delete-value: 1
       # 逻辑未删除值(默认为 0)
        logic-not-delete-value: 0

  2. 修改实体类,添加逻辑删除属性
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student extends Model<Student> {
        private Integer id;
        private String name;
        private String sex;
        private String address;
    
        @Version
        private int version;
    
        @TableLogic
        private int deleted;
    }
    

  3. 修改数据库表,添加一列整型deleted字段并设置默认值为0
  4. 测试删除和查询方法,会看到删除时将deleted字段变为1,查询时添加条件deleted=0

 

@Test
    public void testDelete(){
        studentMapper.deleteById(1);
    }

 

扩展

        自动填充

由于有了逻辑删除字段,那么向数据库插入数据时候,都需要设置deleted=0,而每次插入数据时都要设置该值十分繁琐,于是MyBatisPlus提供了自动填充功能。

  1. 为实体类的自动填充字段添加@TableField
    @TableLogic
    // 自动填充字段
    @TableField(fill=FieldFill.INSERT)
    private Integer deleted;
    填充策略:

描述

DEFAULT

默认不处理

INSERT

插入操作填充字段

UPDATE

更新操作填充字段

INSERT_UPDATE

插入操作和更新操作均填充字段

 

  1. 自定义填充类实现MetaObjectHandler接口,填充类需要放到Spring容器中
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    /**
     * 插入时填充逻辑
     * @param metaObject 元对象
     */

    @Override
    public void insertFill(MetaObject metaObject) {
        /**
         * 参数1:自动填充字段名
         * 参数2:填充值
         * 参数3:元对象
         */
        this.setFieldValByName("deleted",0,metaObject);
    }


    /**
     * 更新时填充逻辑
     * @param metaObject 元对象
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("deleted",0,metaObject);
    }
}

 测试

@Test
    public void testFindAll(){
        Student student = new Student();
        List<Student> students = student.selectAll();
        students.forEach(System.out::println);
    }

        Sql注入器

 MyBatisPlus方法是有限的,我们可以使用SQL注入器自定义全局方法,注入到全局中,这样所有的Mapper类都能使用该方法,接下来我们自定义一个deleteAll方法。

1、创建注入方法类,继承AbstractMethod

2、创建Sql自动注入器,继承AbstractSqlInject,自动注入器需要放到Spring容器中

3、在mapper接口中定义deleteAll方法

4、测试deleteAll方法

public class DeleteAll extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        //定义Sql语句
        String sql = "delete from "+ tableInfo.getTableName();
        //定义方法名
        String method = "deleteAll";
        //构建SqlSource对象,他负责将Sql传递到数据库
        SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration,sql,modelClass);
        //构建删除方法
        return this.addDeleteMappedStatement(mapperClass,method,sqlSource);
    }
}
@Component
public class MySqlInject extends AbstractSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> list = new ArrayList<>();
        list.add(new DeleteAll());
        return list;
    }
}
public interface StudentMapper extends BaseMapper<Student> {
    void deleteAll();
}
@Test
    public void testDeleteAll(){
        studentMapper.deleteAll();
    }

测试,查看数据库

 

 

        代码生成器Generator

如果不想手动编写实体类等文件,MyBaitsPlus提供了代码生成器,它可以读取数据库的表信息,生成MyBaitsPlus代码供我们使用,之前我们学过MyBatis的代码生成器MyBatis Generator,这二者的区别是:

  • MBG基于xml文件配置的,MyBaitsPlus代码生成器是基于Java代码配置的
  • MBG可生成实体类、Mapper接口、Mapper映射文件;
  • MyBaitsPlus代码生成器可生成实体类、Mapper接口、Mapper映射文件、Service类、Controller类

使用:

 

1添加代码生成器所需的依赖

<!-- MyBatisPlus代码生成器 -->

<dependency>

  <groupId>com.baomidou</groupId>

  <artifactId>mybatis-plus-generator</artifactId>

  <version>3.5.1</version>

</dependency>

<!-- MyBatisPlus代码生成器需要的模板引擎 -->

<dependency>

  <groupId>org.apache.velocity</groupId>

  <artifactId>velocity-engine-core</artifactId>

  <version>2.2</version>

</dependency>

2编写代码生成器

public class MyGenerator {

  public static void main(String[] args) {

    FastAutoGenerator.create("jdbc:mysql:///school", "root", "root")

      // 全局配置

       .globalConfig(builder -> {

        builder.author("itbaizhan") // 设置作者

           .commentDate("MM-dd") // 注释日期格式

           .outputDir(System.getProperty("user.dir") + "/springboot_mybatisplus/src/main/java") // 指定输出目录(可能需要更改)

           .fileOverride(); //覆盖文件

       })

      // 包配置

       .packageConfig(builder -> {

        builder.parent("com.itbaizhan.springboot_mp") // 包名前缀(可能需要更改)

           .entity("domain") //实体类包名

           .mapper("mapper") //mapper接口包名

           .service("service") //service包名

           .controller("controller") //controller包名

           .xml("mapper"); //映射文件包名

       })

      // 策略配置

       .strategyConfig(builder -> {

        builder.addInclude("tb_student") // 设置需要生成的表名,可以有多个(可能需要更改)

           .addTablePrefix("tb_") // 设置表名前缀

           .entityBuilder() // 开始实体类配置

           .enableLombok() // 开启lombok模型

           .naming(NamingStrategy.underline_to_camel) //表名下划线转驼峰

           .columnNaming(NamingStrategy.underline_to_camel);//列名下划线转驼峰

       })

       .execute();

   }

}

运行即可生成

 

        代码生成器MyBatisX

MybatisX是一款基于IDEA的快速开发插件,为效率而生。

安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Marketplace,输入 mybatisx 搜索并安装。

生成代码

MybatisX也可以生成Mybatis代码

  1. 在IDEA中连接数据库
  2. 如下操作可以根据数据库表生成Mybaits代码

生成映射配置

  1. 在Mapper接口中编写方法
    public interface StudentMapper extends BaseMapper<Student>{
     
    List<Student> selectAllBySname(String sname);
    }
  2. 如下操作即可在映射文件中自动生成映射配置

代码跳转

点击Mapper接口或映射文件前的小鸟图案,即可快速在Mapper接口与映射文件间跳转

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值