Mybatis-plus

官方网站 Mybatis-plus

一、特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

二、入门案例

运行环境  java17 springboot 3.x  mybatis-plus 3.5.7

1. 数据库的搭建

CREATE DATABASE `mybatis_plus` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
use `mybatis_plus`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL COMMENT '主键ID',
`name` varchar(30) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年龄',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

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');

2. 创建springboot项目引入依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

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

mapper层继承BaseMapper,指名操作的实体类

// 启动类

@SpringBootApplication
@MapperScan("com/study/mapper")
public class MybatisPlusApplication {

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

}

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

// 测试类
@SpringBootTest
class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;

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

遇见 nvalid value type for attribute 'factoryBeanObjectType': java.lang.String,手动升级mybatis-spring

 <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>3.0.3</version>
        </dependency>

添加日志

mybatis-plus:
  configuration:
    # 标准输出
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

三、mybatis-plus的CRUD

1. 增加功能 insert

 public void testInsert() {
        // 新增功能
        User user = new User();
        user.setName("zhangsan");
        user.setAge(23);
        user.setEmail("liubo_china@163.com");
        // insert into user values(?,?,?,?)
        userMapper.insert(user);
        System.out.println(user.getId());

    }

2. 删除功能 delete

 @Test
    public void testDelete() {
        // 通过id删除 DELETE FROM user WHERE id=?
//      int i = userMapper.deleteById(1838410087146074114L);
//      System.out.println("result :" + i);
        // 多个id批量删除 DELETE FROM user WHERE id IN ( ? , ? )
        List<Long> ids = Arrays.asList(1L, 2l);
        int i = userMapper.deleteByIds(ids);
        System.out.println(i);
    }

3. 修改功能 update

public void testUpdate() {
        // 根据ID修改
        User user = new User();
        user.setId(1838409255742861313L);
        user.setName("长子");
        int i = userMapper.updateById(user);

    }

4. 查询功能 select

public void testSelect() {
        // 查询全部
        List<User> users = userMapper.selectList(null);

        // 通过id 查询单条记录
        User user = userMapper.selectById();
        
        // 根据多个id 查询多条数据
        userMapper.selectBatchIds();
    }

5. 自定义功能接口

配置XML文件,自定义sql

5. service接口 

IService 是 MyBatis-Plus 提供的一个通用 Service 层接口,它封装了常见的 CRUD 操作,包括插入、删除、查询和分页等。通过继承 IService 接口,可以快速实现对数据库的基本操作,同时保持代码的简洁性和可维护性。

IService 接口中的方法命名遵循了一定的规范,如 get 用于查询单行,remove 用于删除,list 用于查询集合,page 用于分页查询,这样可以避免与 Mapper 层的方法混淆。

提示

  • 泛型 T 为任意实体对象
  • 建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承 Mybatis-Plus 提供的 IService 基类
  • 对象 Wrapper 为 条件构造器

具体方法实现 见官网 IService

7. 常用注解

@TableName表示实体类与数据表名之间的映射
@TableId(value = )表示实体类的属性为主键,value属性代表与其关联的表中字段名

@Tablefield

@Table

关联字段

四. 条件构造器

1. 条件查询

public void testWrapper() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();

        // select * from user where name like %o% and age between(20,30) and email  not null
        wrapper.like("name","%o%")
                .between("age",20,30)
                .isNotNull("email");
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

2. 指定字段

// 查询指定字段
        QueryWrapper<User> wrapper = new QueryWrapper<>();

        // 查询name age两列
        wrapper.select("name", "age");

        List<User> users = userMapper.selectList(wrapper);
        for (User user : users) {
            System.out.println(user);
        }

3. 子查询

public void testInSql() {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        //select id,name,email,age from user where (id in (select id from user where id <4 ))
        userQueryWrapper.inSql("id","select id from user where id <4 ");
        List<User> users = userMapper.selectList(userQueryWrapper);
        users.forEach(System.out::println);
    }

4. UpdateWrapper修改

 @Test
    public void testUpdateQueryWrapper() {
        // 使用updateWrapper完成修改操作 查询名字含 n 年龄20 30 邮箱不为空的 修改
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();

        updateWrapper.like("name","n").and(i -> i.gt("age",20)) // name > 20
                .or().isNull("email");

        // 设置要修改的指
        updateWrapper.set("name","小黑");
        updateWrapper.set("age",99);
        
        // UPDATE user SET name=?,age=? WHERE (name LIKE ? AND (age > ?) OR email IS NULL)
        int result = userMapper.update(updateWrapper);
        System.out.println("result :" + result);
    }

5. 使用Condition拼接条件

// condition 条件,可以写一个条件判断
        userQueryWrapper.like(StringUtils.isNotBlank(name),"name","n")
                .ge(age != null,"age",20);

6. lambdaQueryWrapper

 // userQueryWrapper.like(StringUtils.isNotBlank(name),"name","n").ge(age != null,"age",20);
lambdaQueryWrapper.like(StringUtils.isNotBlank(name),User::getName,"n").ge(age != null,User::getAge,20);

五、分页功能

1. 配置拦截器 mybatisPlusInterceptor

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {

        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

        return interceptor;
    }


}

2. 使用Page对象实现分页

public void testPage() {
        // 当前页 一页几条内容
        Page<User> userPage = new Page<>(1,2);

        Page<User> selectPage = userMapper.selectPage(userPage, null);
        selectPage.getRecords().forEach(System.out::println); // 获得当前页的记录
        System.out.println(selectPage.getCurrent()); // 当前页
        System.out.println(selectPage.getSize()); // 当前页的条数
        System.out.println(selectPage.getTotal()); // 总记录数
    }

如果没有效果,是因为SpringBoot启动类未扫描到配置类。

@SpringBootApplication(scanBasePackages = {"com.study.config"})
@MapperScan("com/study/mapper")
public class MybatisPlusApplication {

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

}

六、乐观锁和悲观锁

乐观锁

  • 定义:乐观锁假设在大多数情况下不会发生冲突,因此在进行操作时不加锁,而是在提交时检查数据是否被其他事务修改过。
  • 实现方式:通常使用版本号或时间戳来实现。当更新数据时,先检查版本号,如果版本号未改变,则可以成功更新;如果已改变,则需要重试或放弃操作。
  • 优点:减少了锁的竞争,提高了系统的并发性能。
  • 缺点:在高冲突的场景下,可能频繁失败,导致重试次数增加。

乐观锁的实现通常包括以下步骤:

  1. 读取记录时,获取当前的版本号(version)。
  2. 在更新记录时,将这个版本号一同传递。
  3. 执行更新操作时,设置 version = newVersion 的条件为 version = oldVersion
  4. 如果版本号不匹配,则更新失败。

配置类

@Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {

        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        // 乐观锁插件
        
        return interceptor;
    }

实体类表示版本的属性添加@version注解

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

    @Version
    private Integer version;
}

悲观锁

  • 定义:悲观锁假设在大多数情况下会发生冲突,因此在进行任何操作之前都会对所需的数据加锁,以避免其他事务的干扰。
  • 实现方式:通过数据库的行锁或表锁等机制实现。在操作开始时加锁,直到操作完成后再释放锁。
  • 优点:保证了数据的一致性,适合高冲突的场景。
  • 缺点:可能导致性能下降,因为锁会增加等待时间,并且容易出现死锁。

七、通用枚举

将java代码中的枚举类型,指定属性添加到数据库中。如在数据表user中Sex属性为int类型,1代表男,2代表女。枚举属性使用 @EnumValue 注解,指定枚举值在数据库中存储的实际值。支持枚举类中的任意字段,如序号或编码。

public enum SexEnum {
    
    MALE(1,"男"),
    FEMALE(2,"女");
    @EnumValue
    private Integer sex;
    private String sexName;

    SexEnum(Integer sex, String sexName) {
        this.sex = sex;
        this.sexName = sexName;
    }
}

八、代码生成器 代码生成器

九、mybatisX插件的使用

通过模板 快速生成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值