自学内容网 自学内容网

springboot整合mybatis-plus【详细版】

目录

一,简介

1. 什么是mybatis-plus

MyBatis-Plus(简称MP)是一个MyBatis的增强工具,旨在在MyBatis的基础上只做增强不做改变,以简化开发、提高效率。MyBatis-Plus保持了MyBatis原有的所有特性,同时增加了一些实用的功能,使得开发者能够更加便捷地进行数据库操作。以下是MyBatis-Plus的一些主要特点和功能:

2.mybatis-plus特点

  1. 无侵入:引入MyBatis-Plus不会对现有的MyBatis工程产生影响,可以无缝集成到现有的项目中。
    损耗小:启动时自动注入基本的CRUD操作,几乎不消耗额外的性能,可以直接面向对象操作数据库。
  2. 强大的CRUD操作:内置通用Mapper、通用Service,通过少量配置即可实现单表的大部分CRUD操作。同时,MyBatis-Plus提供了强大的条件构造器,满足复杂的查询需求。
  3. 支持Lambda形式调用:利用Lambda表达式方便地编写查询条件,避免了字段名称错误的问题。
  4. 支持主键自动生成:提供了多种主键生成策略,包括分布式唯一ID生成器,解决了主键问题。
  5. 支持ActiveRecord模式:通过继承特定的基类,可以像操作对象一样操作数据库。
  6. 支持自定义全局通用操作:允许开发者注入自己的通用方法。
  7. 内置分页插件:基于MyBatis的物理分页,开发者可以轻松实现分页查询。
  8. 支持多种数据库:兼容MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、PostgreSQL、SQL Server等多种数据库。
  9. 内置性能分析插件:可以输出SQL语句及其执行时间,有助于快速定位慢查询。
  10. 内置全局拦截插件:提供全表删除、更新操作的智能分析阻断,防止误操作。

二,搭建基本环境

1. 导入基本依赖:

      <!--mybatis-plus依赖-->
      <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.7</version>
        </dependency>
<!--mysql连接依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <!--连接池依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.18</version>
        </dependency>

2. 编写配置文件

spring:
  data:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_study?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource

3. 创建实体类

package org.example.pojo;


import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.util.Date;
@TableName("student")
public class Student {
    @TableId(type = IdType.AUTO)
    private int id;
    
    private String studentNumber;
    
    private String name;
    
    private int gender; 
    // 0 表示女性,1 表示男性
    private Date dateOfBirth;
   // Getters and Setters
    }

4. 编写controller层

package org.example.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/students")
public class StudentController {
    
}

5. 编写service接口

package org.example.service;

import com.baomidou.mybatisplus.extension.service.IService;
import org.example.pojo.Student;

public interface StudentService extends IService<Student> {
}

6. 编写service层

package org.example.service.serviceImpl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.mapper.StudentMapper;
import org.example.pojo.Student;
import org.example.service.StudentService;
import org.springframework.stereotype.Service;

@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

}

7. 编写mapper层

package org.example.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.example.pojo.Student;

@Mapper
public interface StudentMapper extends BaseMapper<Student> {
}

三,基本知识介绍

1. 基本注解

@TableName

主要用于指定表名,实现实体类与表名的绑定,作用于类上,适用于表名与实体类名称不统一的情况,统一的情况可以不用写。
在这里插入图片描述

import com.baomidou.mybatisplus.annotation.TableName;
//此处表名称为t_user,实体类名称为User不统一
@TableName("t_user")
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;

    // Getters and Setters
}

如果所有的表结构与实体类只是多了一个前缀,可以直接在配置文件里面配置全局的前缀,就可以不使用注解了,两种方式都可以,根据具体场景选择,配置如下:

mybatis-plus:
  global-config:
    db-config:
      table-prefix: t_
@TableId

作用于主键上,指明主键字段,并设置主键的生成方式。

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;

@TableName("user_info") // 指定该实体类对应的数据表名
public class UserInfo {
//此处value也可以作用于映射,当实体类中
//的id字段名和数据库中的字段名不相同时,可以使用其属性做增强
    @TableId(value = "id", type = IdType.AUTO) // 标记为主键,并指定主键生成策略为自增
    private Long id;

    private String username;
    
    private String password;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}


注解属性:
   value:指定表中主键字段,多用于主键字段和实体类字段不同意
    type:id生成策略

对于IdType做出如下说明:

属性

说明

适用场景

AUTO

数据库自增主键

适用于 MySQL、SQL Server 等支持自增主键的数据库

NONE

不使用任何主键生成策略

通常用于主键已经存在的情况

ASSIGN_ID

全局唯一ID(默认基于Snowflake算法生成)

适用于分布式系统,确保全局唯一性

ASSIGN_UUID

全局唯一UUID,生成32位的字符串

适用于需要字符串主键的场景

INPUT

自定义输入主键值

适用于某些特殊场景,如导入数据时需要手动指定主键

@TableFiled

改注解作用众多,多用于表字段和实体类字段名称不统一,做映射处理,也可用于零时字段,不存入数据库,或者是一些字段的填充处理(此处需要编写填充处理器)。
在这里插入图片描述

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;

import java.util.Date;

@TableName("user_info")
public class UserInfo {

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @TableField("username")
    private String username;
//此字段不参与查询
    @TableField("password", select=false )
    private String password;

    @TableField("email")
    private String email;
//注意,此处应该编写相应的填充逻辑
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    private Date createTime;

    @TableField(value = "update_time", fill = FieldFill.UPDATE)
    private Date updateTime;

    @TableField(exist = false)
    private String tempField; // 临时字段,不在数据库中

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public String getTempField() {
        return tempField;
    }

    public void setTempField(String tempField) {
        this.tempField = tempField;
    }
}


属性说明:
value:同上面注解一样,用于字段绑定,单个属性的时候可以不写
select:在值为false的情况下用于设置不参查询,查询之后不会返回回来
exist :用于类中的零时变量,数据库中没有该字段,只在java中使用
fill:用于自动填充,比如create_time,update_time这一类,但需要编写相应的处理器

对应处理器代码:

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
        this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
    }
}
@TableLogic

该字段用于指定逻辑删除的字段,当执行删除语句时,做更新操作,只改变当前字段的值,设置为删除状态,数据不做真实处理,查询时也只查询状态为未删除的数据(此过程不需要手动实现,mybatis-plus已经帮忙实现了,我们只需要添加字段,设置相应的状态值)注:该字段也需要加入到对应的表里

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;

@TableName("user_info")
public class UserInfo {

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    private String username;

    private String password;

    private String email;

    @TableLogic
    private Integer isDeleted;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getIsDeleted() {
        return isDeleted;
    }

    public void setIsDeleted(Integer isDeleted) {
        this.isDeleted = isDeleted;
    }
}

在配置文件中添加如下配置:

mybatis-plus:
  global-config:
    db-config:
      # 逻辑删除字段名
      logic-delete-field: deleted
      # 逻辑删除字面值:未删除为0
      logic-not-delete-value: 0
      # 逻辑删除字面值:删除为1
      logic-delete-value: 1
@Version

用于配置乐观锁字段,配置之后的更新操作都会先去比较版本,然后在去操作,整体采用cas机制实现。注:该字段也需要加入到对应的表里

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.Version;

@TableName("order_info")
public class OrderInfo {

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    private String orderNo;

    private Double amount;

    @Version
    private Integer version;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    public Double getAmount() {
        return amount;
    }

    public void setAmount(Double amount) {
        this.amount = amount;
    }

    public Integer getVersion() {
        return version;
    }

    public void setVersion(Integer version) {
        this.version = version;
    }
}

此处需加相关的拦截器:

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}


乐观锁的作用:
乐观锁假设在并发环境中冲突较少,因此在操作数据时不立即获取锁,而是等到提交更新时才检查是否有其他事务修改过数据。如果发现数据已被修改,则更新失败,通常会抛出异常。
    特点:在提交更新时检查版本号,如果版本号匹配则更新成功,否则更新失败。
效果:多个事务可以同时读取和处理数据,但在提交更新时会检查版本号,确保数据的一致性。
@Transient

作用于实体类字段,使其不参与数据库的操作,其中包括(Insert,Update,Select),@TableField(exist=false)作用相同,充当零时变量。

@TableName("user")
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;

    private String name;

    @Transient
    private String tempField;

    // getters and setters
}

2. Wrapper的介绍*

概念:MyBatisPlus提供了QueryWrapper、LambdaQueryWrapper、UpdateWrapper和LambdaUpdateWrapper等条件类,大大简化了我们的开发,可以使代码更加清晰和易于管理,其中包括多条件查询、排序、条件优先级以及有条件时才加入条件的场景,并提供了示例代码展示如何进行数据库查询和更新操作。

大致的条件(此处粗略列举):

方法

描述

eq

等于

ne

不等于

gt

大于

ge

大于等于

lt

小于

le

小于等于

like

模糊查询

notLike

反向模糊查询

in

在某集合内

notIn

不在某集合内

isNull

为空

isNotNull

不为空

between

在某个区间内

notBetween

不在某个区间内

set

设置字段值

QueryWrapper

作用于查询设置查询条件。

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

public class UserService {
    private UserMapper userMapper;

    public List<User> getUsersByConditions() {
        // 创建 QueryWrapper 对象
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        
        // 添加查询条件
        queryWrapper.eq("name", "张三")
                    .ge("age", 18)
                    .orderByDesc("create_time");

        // 执行查询
        return userMapper.selectList(queryWrapper);
    }
}

此处执行的sql语句:

SELECT * FROM user WHERE name = '张三' AND age >= 18 ORDER BY create_time DESC;
UpdateWrapper

作用于更新设置条件。

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

public class UserService {
    private UserMapper userMapper;

    public int updateUserById() {
        // 创建 UpdateWrapper 对象
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        
        // 添加更新条件
        updateWrapper.eq("id", 1);

        // 创建要更新的对象
        User user = new User();
        user.setName("李四");

        // 执行更新
        return userMapper.update(user, updateWrapper);
    }
}

此处执行的sql语句:

UPDATE user SET name = '李四' WHERE id = 1;
LambdaQueryWrapper

在QueryWrapper做了增强,作用一样,用于设置查询条件。

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

public class UserService {
    private UserMapper userMapper;

    public List<User> getUsersByLambdaConditions() {
        // 创建 LambdaQueryWrapper 对象
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        lambdaQueryWrapper.eq(User::getName, "张三")
                          .ge(User::getAge, 18)
                          .orderByDesc(User::getCreateTime);

        // 执行查询
        return userMapper.selectList(lambdaQueryWrapper);
    }
}

此处执行的sql语句:

SELECT * FROM user WHERE name = '张三' AND age >= 18 ORDER BY create_time DESC;
LambdaUpdateWrapper

在UpdateWrapper做了增强,作用一样,用于设置跟新条件。

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

public class UserService {
    private UserMapper userMapper;

    public int updateUserByIdWithLambda() {
        // 创建 LambdaUpdateWrapper 对象
        LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        
        // 添加更新条件
        lambdaUpdateWrapper.eq(User::getId, 1);

        // 创建要更新的对象
        User user = new User();
        user.setName("李四");

        // 执行更新
        return userMapper.update(user, lambdaUpdateWrapper);
    }
}

此处执行的sql语句:

UPDATE user SET name = '李四' WHERE id = 1;
Wrappers

用于更简便的条件设置

import com.baomidou.mybatisplus.core.toolkit.Wrappers;

public class UserService {
    private UserMapper userMapper;

    public List<User> getUsersByConditionsUsingWrappers() {
        // 创建 QueryWrapper 对象
        QueryWrapper<User> queryWrapper = Wrappers.<User>query()
                                                  .eq("name", "张三")
                                                  .ge("age", 18)
                                                  .orderByDesc("create_time");

        // 执行查询
        return userMapper.selectList(queryWrapper);
    }
}

此处执行的sql语句:

SELECT * FROM user WHERE name = '张三' AND age >= 18 ORDER BY create_time DESC;

3. 分页查询

1. 配置相应的拦截器
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}
2. 实现分页逻辑
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public IPage<User> getUserPage(int current, int size) {
        // 创建 Page 对象,传入当前页码和每页大小
        Page<User> page = new Page<>(current, size);

        // 创建 QueryWrapper 对象,添加查询条件
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 1)
                    .orderByDesc("create_time");

        // 执行分页查询
        IPage<User> userPage = userMapper.selectPage(page, queryWrapper);
// 获取分页数据
List<User> users = userPage.getRecords();

// 获取总记录数
long total = userPage.getTotal();

// 获取当前页码
int current = userPage.getCurrent();

// 获取每页大小
int size = userPage.getSize();

// 获取总页数
int pages = userPage.getPages();
        return userPage;
    }
}

执行对应的sql语句是:

-- 分页查询
SELECT * 
FROM user 
WHERE status = 1 
ORDER BY create_time DESC 
LIMIT 0, 10; -- 当前页码为1,每页大小为10

四,结语

在本文中,我们详细介绍了 MyBatis-Plus 的核心功能和使用方法,包括如何配置分页插件、编写分页查询代码、使用各种 Wrapper 构建复杂查询条件等。通过这些内容,相信你已经对 MyBatis-Plus 有了更深入的了解,并能够在实际项目中灵活应用这些功能。
MyBatis-Plus 作为一个强大的 MyBatis 增强工具,不仅简化了数据访问层的开发工作,还提供了许多便捷的功能,如分页查询、链式编程、乐观锁等。它能够显著提升开发效率,减少重复代码,使你的项目更加简洁和高效。
如果你在阅读本文后对 MyBatis-Plus 感兴趣,不妨在自己的项目中尝试一下。实践是最好的老师,通过实际操作,你会更加深刻地理解这些功能的奥妙。同时,也欢迎你在评论区分享你的使用经验和遇到的问题,我们一起探讨和解决。
最后,感谢你花时间阅读本文,希望本文能为你带来帮助。如果你觉得本文对你有帮助,别忘了点赞和分享,让更多的人受益。让我们一起在技术的道路上不断前行,共同成长!


原文地址:https://blog.csdn.net/m0_74825678/article/details/145202952

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!