当前位置: 首页 > news >正文

MybatisPlus 快速入门

目录

简介

安装

Spring Boot2

Spring Boot3

Spring

配置

Spring Boot 工程

Spring 工程

常见注解

条件构造器

流式查询

使用示例

批量操作

使用示例

自定义SQL

Service接口

CRUD

扩展功能

代码生成

安装插件

通用枚举

配置枚举处理器

插件功能

配置示例


简介

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

特性

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

安装

Spring Boot2

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.7</version>
</dependency>

Spring Boot3

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.7</version>
</dependency>

Spring

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><version>3.5.7</version>
</dependency>

注意事项

        引入 MyBatis-Plus 之后请不要再次引入 MyBatis 以及 mybatis-spring-boot-starter和MyBatis-Spring,以避免因版本差异导致的问题。

        自3.5.4开始,在没有使用mybatis-plus-boot-starter或mybatis-plus-spring-boot3-starter情况下,请自行根据项目情况引入mybatis-spring。

配置

Spring Boot 工程

配置 MapperScan 注解

@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}}

大多数的配置都有默认值,因此我们都无需配置。但还有一些是没有默认值的,例如:

1、实体类的别名扫描包

2、全局id类型

mybatis-plus:type-aliases-package: com.itheima.mp.domain.poglobal-config:db-config:id-type: auto # 全局id类型为自增长

需要注意的是,MyBatisPlus也支持手写SQL的,而mapper文件的读取地址可以自己配置:+

mybatis-plus:mapper-locations: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,当前这个是默认值。

可以看到默认值是classpath*:/mapper/**/*.xml,也就是说我们只要把mapper.xml文件放置这个目录下就一定会被加载。

Spring 工程

配置 MapperScan

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.baomidou.mybatisplus.samples.quickstart.mapper"/>
</bean>

调整 SqlSessionFactory 为 MyBatis-Plus 的 SqlSessionFactory

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/>
</bean>

常见注解

1、@TableName

用于指定数据库表名。通常与实体类一起使用,用于映射数据库表。

TableName注解除了指定表名以外,还可以指定很多其它属性:

属性

类型

必须指定

默认值

描述

value

String

""

表名

schema

String

""

schema

keepGlobalPrefix

boolean

false

是否保持使用全局的 tablePrefix 的值(当全局 tablePrefix 生效时)

resultMap

String

""

xml 中 resultMap 的 id(用于满足特定类型的实体类对象绑定)

autoResultMap

boolean

false

是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建与注入)

excludeProperty

String[]

{}

需要排除的属性名 @since 3.3.1

2、@TableId
用于标识实体类中的主键字段。可以指定主键的生成策略。

TableId注解支持两个属性:

属性

类型

必须指定

默认值

描述

value

String

""

表名

type

Enum

IdType.NONE

指定主键类型

IdType支持的类型有:

描述

AUTO

数据库 ID 自增

NONE

无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)

INPUT

insert 前自行 set 主键值

ASSIGN_ID

分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)

ASSIGN_UUID

分配 UUID,主键类型为 String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认 default 方法)

ID_WORKER

分布式全局唯一 ID 长整型类型(please use ASSIGN_ID)

UUID

32 位 UUID 字符串(please use ASSIGN_UUID)

ID_WORKER_STR

分布式全局唯一 ID 字符串类型(please use ASSIGN_ID)

这里比较常见的有三种:

  • AUTO:利用数据库的id自增长
  • INPUT:手动生成id
  • ASSIGN_ID:雪花算法生成Long类型的全局唯一id,这是默认的ID策略

3、@TableField
用于指定实体类字段与数据库表字段的映射关系。它可以用于自定义列名、是否插入、更新等。

一般情况下我们并不需要给字段添加@TableField注解,一些特殊情况除外:

1、成员变量名与数据库字段名不一致

如果实体类中的字段名与数据库表中的列名不一致,可以使用 @TableField 注解来指定数据库中的列名:

@TableField(value = "db_column_name")
private String entityFieldName;

2、成员变量是以 isXXX 命名

按照 JavaBean 规范,如果字段以 is 开头,MyBatis-Plus 默认会去掉 is 部分来进行映射。如果数据库字段名与去掉 is 后的变量名不一致,需要用 @TableField 指定数据库中的列名:

@TableField(value = "db_column_name")
private Boolean isActive;

3、成员变量名与数据库字段一致,但与数据库关键字冲突

如果字段名与数据库中的关键字冲突,可以使用反引号 ```` 来处理:

@TableField(value = "`key`")
private String key;

支持的其它属性如下:

属性

类型

必填

默认值

描述

value

String

""

数据库字段名

exist

boolean

true

是否为数据库表字段

condition

String

""

字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s},参考(opens new window)

update

String

""

字段 update set 部分注入,例如:当在version字段上注解update="%s+1" 表示更新时会 set version=version+1 (该属性优先级高于 el 属性)

insertStrategy

Enum

FieldStrategy.DEFAULT

举例:NOT_NULL insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>)

updateStrategy

Enum

FieldStrategy.DEFAULT

举例:IGNORED update table_a set column=#{columnProperty}

whereStrategy

Enum

FieldStrategy.DEFAULT

举例:NOT_EMPTY where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if>

fill

Enum

FieldFill.DEFAULT

字段自动填充策略

select

boolean

true

是否进行 select 查询

keepGlobalFormat

boolean

false

是否保持使用全局的 format 进行处理

jdbcType

JdbcType

JdbcType.UNDEFINED

JDBC 类型 (该默认值不代表会按照该值生效)

typeHandler

TypeHander

类型处理器 (该默认值不代表会按照该值生效)

numericScale

String

""

指定小数点后保留的位数

条件构造器

MyBatis-Plus 的条件构造器(Wrapper)确实提供了强大且灵活的功能,用于构建各种数据库查询和更新条件。

1. AbstractWrapper

AbstractWrapper 是所有 Wrapper 类的基类,定义了构造查询和更新条件的基础方法和属性,包括字段、值、操作符等。其他具体的 Wrapper 类(如 QueryWrapper、UpdateWrapper、LambdaQueryWrapper 和 LambdaUpdateWrapper)都继承自它。

2. QueryWrapper

QueryWrapper 用于构造查询条件,支持多种操作符和逻辑组合。可以通过链式调用添加多个查询条件,并通过 and 和 or 来组合条件。

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("status", 1).gt("age", 18).or().like("name", "John");List<User> users = userMapper.selectList(queryWrapper);

在上面的例子中,eq 表示等于,gt 表示大于,or 表示逻辑“或”,like 表示模糊匹配。 

3. UpdateWrapper
UpdateWrapper 用于构造更新条件,它允许你在更新数据时指定条件。它的使用方法与 QueryWrapper 类似。

UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("status", 1).set("age", 30).set("name", "Updated Name");userMapper.update(null, updateWrapper);

在这个例子中,set 用于指定需要更新的字段及其新值。 

4. LambdaQueryWrapper

LambdaQueryWrapper 允许使用 Lambda 表达式来引用实体类的属性,避免了硬编码字段名的问题,从而提高了代码的可读性和可维护性。

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getStatus, 1).gt(User::getAge, 18).or().like(User::getName, "John");List<User> users = userMapper.selectList(lambdaQueryWrapper);

5. LambdaUpdateWrapper

LambdaUpdateWrapper 与 LambdaQueryWrapper 类似,但用于构造更新条件。它允许使用 Lambda 表达式来设置更新字段及条件。

LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.eq(User::getStatus, 1).set(User::getAge, 30).set(User::getName, "Updated Name");userMapper.update(null, lambdaUpdateWrapper);

流式查询

MyBatis-Plus 从 3.5.4 版本开始支持流式查询,这使得在处理大数据量时更加高效。流式查询通过 ResultHandler 接口实现,可以有效地避免将整个结果集加载到内存中,适合用于数据跑批或大规模数据处理的场景。

常用方法

在 ResultHandler 中,可以使用以下方法来处理查询结果:

  • getResultObject(): 获取当前数据库中的每一条记录。
  • getResultCount(): 获取当前处理的结果集条数,每处理一条记录,该计数器会加1,计数从1开始。
  • stop(): 停止继续处理结果集,相当于在循环中使用 break 语句。

使用示例

以下是官网使用流式查询的示例代码,展示了如何结合分页从数据库中拉取数据进行批量处理,以及如何获取表中的所有记录进行处理。

// 结合分页,按批次从数据库拉取数据出来跑批,例如从数据库获取10万记录,做数据处理
Page<H2User> page = new Page<>(1, 100000);
baseMapper.selectList(page, Wrappers.emptyWrapper(), new ResultHandler<H2User>() {int count = 0;@Overridepublic void handleResult(ResultContext<? extends H2User> resultContext) {H2User h2User = resultContext.getResultObject();System.out.println("当前处理第" + (++count) + "条记录: " + h2User);// 在这里进行你的业务处理,比如分发任务}
});// 从数据库获取表所有记录,做数据处理
baseMapper.selectList(Wrappers.emptyWrapper(), new ResultHandler<H2User>() {int count = 0;@Overridepublic void handleResult(ResultContext<? extends H2User> resultContext) {H2User h2User = resultContext.getResultObject();System.out.println("当前处理第" + (++count) + "条记录: " + h2User);// 在这里进行你的业务处理,比如分发任务}
});

注意事项

  • 分页查询与流式查询: 在低版本的 MyBatis-Plus 中,自定义 ResultHandler 结合分页查询可能会出现问题。解决方案是手动关闭 count 查询
  • 资源管理: 使用流式查询时,确保数据库连接在操作完成后被正确关闭,避免连接泄露问题。
  • 性能优化: 流式查询适合于大数据量的场景,不适合处理小数据量的查询,因其可能引入不必要的复杂性。

批量操作

批量操作是处理大量数据时的一种高效技术,它通过一次性执行多个数据库操作来提高效率和性能。常见的批量操作包括:

  1. 数据插入:一次性插入多条记录,减少SQL执行次数,加快数据写入速度。
  2. 数据更新:同时更新多条记录的特定字段,适用于批量修改数据的场景。
  3. 数据删除:快速删除多条记录,适合数据清理和用户注销等操作。

功能概览

  • 支持版本:3.5.4及以上版本
  • 事务控制:需手动管理(默认关闭)
  • 执行结果:返回批量处理结果,帮助判断操作是否成功
  • 数据写入:取决于代码是否正确执行到flushStatements
  • 兼容性:支持Spring和非Spring项目
  • 异常类型:可能会抛出PersistenceException
  • 建议:对于saveOrUpdate方法,建议简单处理新增或更新操作

类结构说明

MybatisBatch<?>

  • 泛型:实际数据类型
  • sqlSessionFactory:通过容器获取,非Spring容器下需手动初始化
  • dataList:批量数据处理列表(不能为空)

MybatisBatch.Method<?>

  • 实际为BatchMethod,用于简化框架内部操作方法的调用
  • 泛型:实际Mapper方法参数类型
  • mapperClass:具体的Mapper类

BatchMethod<?>

  • 泛型:实际Mapper方法参数类型
  • statementId:执行的MappedStatement ID
  • parameterConvert:用于数据类型与Mapper方法参数不一致时的转换处理器

使用步骤

  1. 创建MybatisBatch实例:绑定数据列表和sqlSessionFactory。
  2. 创建MybatisBatch.Method实例:确定执行的Mapper类方法。
  3. 执行操作:将批量参数转换为Mapper方法所需的参数。
  4. 处理返回值:返回List<BatchResult>,每个BatchResult代表一次MappedStatement的操作结果。

返回值说明

  • 返回类型:List<BatchResult>
  • 返回内容:分组存储每次MappedStatement + SQL操作的结果。例如,批量更新时,返回值将根据更新字段的不同分组,显示每组记录的更新情况。

使用示例

execute 方法

execute 方法通常用于直接执行批量操作,例如批量插入或更新。它通过指定的 SQL 语句执行批量处理。在 MyBatis-Plus 中,这通常涉及到使用 SqlSession 执行自定义 SQL。

public void executeBatch(List<MyEntity> entities) {SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);try {MyMapper mapper = sqlSession.getMapper(MyMapper.class);for (MyEntity entity : entities) {mapper.insert(entity); // 执行插入操作}sqlSession.commit(); // 提交事务} catch (Exception e) {sqlSession.rollback(); // 回滚事务throw e;} finally {sqlSession.close();}
}

saveOrUpdate 方法

saveOrUpdate 方法用于处理批量保存或更新操作,自动决定记录是插入还是更新。+

注意:跨sqlSession下需注意缓存和数据感知问题。

public void saveOrUpdateBatch(List<MyEntity> entities) {SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);try {MyMapper mapper = sqlSession.getMapper(MyMapper.class);for (MyEntity entity : entities) {if (entity.getId() == null || mapper.selectById(entity.getId()) == null) {mapper.insert(entity); // 插入操作} else {mapper.updateById(entity); // 更新操作}}sqlSession.commit(); // 提交事务} catch (Exception e) {sqlSession.rollback(); // 回滚事务throw e;} finally {sqlSession.close();}
}

事务处理示例

在 MyBatis-Plus 中,事务管理可以通过 Spring 的事务管理器或 MyBatis 的原生事务控制进行。

Spring 事务处理示例:

@Service
public class MyService {@Autowiredprivate MyMapper myMapper;@Transactional // 事务注解public void batchProcess(List<MyEntity> entities) {for (MyEntity entity : entities) {myMapper.insert(entity); // 执行插入操作}}
}

手动事务处理示例:

public void manualTransaction(List<MyEntity> entities) {SqlSession sqlSession = sqlSessionFactory.openSession();try {MyMapper mapper = sqlSession.getMapper(MyMapper.class);for (MyEntity entity : entities) {mapper.insert(entity); // 执行插入操作}sqlSession.commit(); // 提交事务} catch (Exception e) {sqlSession.rollback(); // 回滚事务throw e;} finally {sqlSession.close();}
}

自定义SQL

sql

-- 1,删除数据库drop database if exists test;
-- 2,创建数据库create database test;
-- 3,修改数据库编码方式和字符集排列顺序alter database test character set utf8 collate utf8_bin;
-- 4,使用数据库use test;-- 创建教师表
CREATE TABLE teacher (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) NOT NULL,subject VARCHAR(100) NOT NULL
);-- 创建班级表
CREATE TABLE class (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) NOT NULL,teacher_id INT,FOREIGN KEY (teacher_id) REFERENCES teacher(id)
);-- 创建学生表
CREATE TABLE student (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) NOT NULL,age INT NOT NULL,class_id INT,FOREIGN KEY (class_id) REFERENCES class(id)
);
-- 插入教师数据
INSERT INTO teacher (name, subject) VALUES
('李华', '数学'),
('张伟', '物理'),
('王芳', '历史');-- 插入班级数据,并关联教师
INSERT INTO class (name, teacher_id) VALUES
('数学101', 1),   -- 由李华教授
('物理101', 2),   -- 由张伟教授
('历史101', 3);   -- 由王芳教授-- 插入学生数据,并关联班级
INSERT INTO student (name, age, class_id) VALUES
('小明', 15, 1),  -- 在数学101班级
('小红', 16, 1),  -- 在数学101班级
('小刚', 15, 2),  -- 在物理101班级
('小李', 17, 2),  -- 在物理101班级
('小华', 16, 3);  -- 在历史101班级

查询李华教授带的课程,班级,学生数据

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.TeacherMapper"><!-- 查询李华教授带的课程、班级和学生数据 --><select id="findTeacherClassesAndStudents" resultType="map">SELECTt.name AS teacher_name,c.name AS class_name,s.name AS student_name,s.age AS student_ageFROM teacher tJOIN class c ON t.id = c.teacher_idJOIN student s ON c.id = s.class_idWHERE t.name = '李华'</select>
</mapper>
package com.example.demo.mapper;import com.example.demo.entity.Teacher;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;/*** <p>*  Mapper 接口* </p>** @author * @since 2024-09-08*/
@Mapper
public interface TeacherMapper extends BaseMapper<Teacher> {List<Map<String, Object>> findTeacherClassesAndStudents();
}
package com.example.demo.service.impl;import com.example.demo.entity.Teacher;
import com.example.demo.mapper.TeacherMapper;
import com.example.demo.service.ITeacherService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.Map;/*** <p>*  服务实现类* </p>** @author * @since 2024-09-08*/
@Service
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements ITeacherService {@Autowiredprivate TeacherMapper teacherMapper;public List<Map<String, Object>> getTeacherClassesAndStudents() {return teacherMapper.findTeacherClassesAndStudents();}
}
package com.example.demo.controller;import com.example.demo.service.impl.TeacherServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.List;
import java.util.Map;/*** <p>*  前端控制器* </p>** @author * @since 2024-09-08*/
@RestController
@RequestMapping("/teacher")
public class TeacherController {@Autowiredprivate TeacherServiceImpl teacherService;@GetMapping("/classes")public List<Map<String, Object>> getTeacherClassesAndStudents() {return teacherService.getTeacherClassesAndStudents();}
}

Service接口

MybatisPlus不仅提供了BaseMapper,还提供了通用的Service接口及默认实现,封装了一些常用的service模板方法。 通用接口为IService,默认实现为ServiceImpl,其中封装的方法可以分为以下几类:

  • save:新增
  • remove:删除
  • update:更新
  • get:查询单个结果
  • list:查询集合结果
  • count:计数
  • page:分页查询

CRUD

我们先俩看下基本的CRUD接口。

新增

  •  save - 新增单个元素:用于新增单个记录。它会根据实体类的字段进行插入操作。
  •  saveBatch - 批量新增:用于批量新增多条记录。适合在一次操作中插入多个实体对象,提高插入效率。
  • saveOrUpdate - 根据 ID 判断新增或更新:如果实体对象的 ID 存在于数据库中,则执行更新操作;如果 ID 不存在,则执行插入操作。
  • saveOrUpdateBatch - 批量的新增或修改:批量处理实体对象,根据每个对象的 ID 判断是执行插入还是更新操作。

删除:

​​​​​​​

  • removeById - 根据 ID 删除:删除指定 ID 的记录。
  • removeByIds - 批量根据 ID 删除:删除多个指定 ID 的记录。
  • removeByMap - 根据 Map 中的条件删除:根据 Map 中的键值对作为条件进行删除。
  • remove(Wrapper<T>) - 根据 Wrapper 条件删除:使用 Wrapper 对象中定义的条件进行删除。
  • removeBatchByIds 方法已不再支持,建议使用 removeByIds 进行批量删除操作。

修改:

  • updateById - 根据 ID 修改:根据指定 ID 更新记录。需要提供更新后的实体对象。
  • update(Wrapper<T>) - 根据 UpdateWrapper 修改:使用 UpdateWrapper 进行条件更新。需要定义更新的字段和条件。
  • update(T, Wrapper<T>) - 按照实体数据和 Wrapper 修改:根据实体对象中的数据和 Wrapper 中的条件进行更新。实体对象中的字段会被更新到符合 Wrapper 条件的记录中。
  • updateBatchById - 根据 ID 批量修改:根据多个 ID 批量更新记录。实体对象中的数据会更新到对应的 ID 中。

Get:

  • getById - 根据 ID 查询:根据指定 ID 获取一条记录。
  • getOne(Wrapper<T>) - 根据 Wrapper 查询:使用 Wrapper 条件获取一条记录。如果有多条记录符合条件,只会返回其中一条。
  • getBaseMapper - 获取 BaseMapper 实现:获取 Service 内的 BaseMapper 实现,以便进行自定义 SQL 操作或其他特殊操作。

List:

  • listByIds - 根据 ID 批量查询:根据多个 ID 获取对应的记录。
  • list(Wrapper<T>) - 根据 Wrapper 条件查询:使用 Wrapper 条件获取多条记录。
  • list() - 查询所有:获取所有记录。

Count

  • count() - 统计所有记录的数量:统计数据库中所有记录的总数。
  • count(Wrapper<T>) - 统计符合 Wrapper 条件的记录数量:使用 Wrapper 条件统计符合条件的记录数量。

getBaseMapper

getBaseMapper 方法允许在 Service 中直接获取 Mapper 实现,以便执行自定义 SQL 查询或操作。

TeacherMapper teacherMapper = teacherService.getBaseMapper();
List<Teacher> teachers = teacherMapper.customQueryMethod();

这样,可以在 Mapper 中定义自定义的 SQL 方法,并通过 getBaseMapper 直接调用。

扩展功能

代码生成

MybatisPlus 提供的代码生成器可以大大简化代码编写工作,但使用起来可能有些复杂。推荐的图形化插件能够通过友好的界面完成代码生成,简化了配置和操作流程。这样的工具能有效提升开发效率,减少手动编写基础代码的工作量。

安装插件

在Idea的plugins市场中搜索并安装MyBatisPlus插件:

然后重启你的Idea即可使用。

通用枚举

sql

-- 1,删除数据库drop database if exists test;
-- 2,创建数据库create database test;
-- 3,修改数据库编码方式和字符集排列顺序alter database test character set utf8 collate utf8_bin;
-- 4,使用数据库use test;-- 创建教师表
CREATE TABLE teacher (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) NOT NULL,subject VARCHAR(100) NOT NULL
);-- 创建班级表
CREATE TABLE class (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) NOT NULL,teacher_id INT,FOREIGN KEY (teacher_id) REFERENCES teacher(id)
);-- 创建学生表
CREATE TABLE student (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) NOT NULL,age INT NOT NULL,class_id INT,gender ENUM('Male', 'Female') NOT NULL,FOREIGN KEY (class_id) REFERENCES class(id)
);-- 插入教师数据
INSERT INTO teacher (name, subject) VALUES
('李华', '数学'),
('张伟', '物理'),
('王芳', '历史');-- 插入班级数据,并关联教师
INSERT INTO class (name, teacher_id) VALUES
('数学101', 1),
('物理101', 2),
('历史101', 3);-- 插入学生数据,并关联班级
INSERT INTO student (name, age, class_id, gender) VALUES
('小明', 15, 1, 'Male'),
('小红', 16, 1, 'Female'),
('小刚', 15, 2, 'Male'),
('小李', 17, 2, 'Male'),
('小华', 16, 3, 'Female');

定义通用枚举

public enum Gender {MALE("Male"),FEMALE("Female");private final String description;Gender(String description) {this.description = description;}public String getDescription() {return description;}
}

假设在 Java 中处理这些数据,可以在实体类中添加枚举字段: 

public class Student {private Long id;private String name;private int age;private Long classId;private Gender gender;
}

配置枚举处理器

在application.yaml文件中添加配置:

mybatis-plus:configuration:default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler

插件功能

  • PaginationInnerInterceptor(自动分页):自动处理分页查询。
  • TenantLineInnerInterceptor(多租户):实现多租户功能,通过 SQL 查询条件自动添加租户信息。
  • DynamicTableNameInnerInterceptor(动态表名):允许动态更改 SQL 查询中的表名。
  • OptimisticLockerInnerInterceptor(乐观锁):实现乐观锁机制,避免数据的并发更新冲突。
  • IllegalSQLInnerInterceptor(SQL 性能规范):检查 SQL 语句的规范性,避免不合理的 SQL。
  • BlockAttackInnerInterceptor(防止全表更新与删除):防止全表更新和删除操作,避免误操作。

插件定义顺序

使用多个插件时,需要注意插件的定义顺序以确保插件功能的正常运行。通常的顺序如下:

  1. 多租户(TenantLineInnerInterceptor)
  2. 动态表名(DynamicTableNameInnerInterceptor)
  3. 分页(PaginationInnerInterceptor)
  4. 乐观锁(OptimisticLockerInnerInterceptor)
  5. SQL 性能规范(IllegalSQLInnerInterceptor)
  6. 防止全表更新与删除(BlockAttackInnerInterceptor)

配置示例

下面是一个示例配置,演示如何按照顺序注册这些插件:

package com.example.demo.Config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** MybatisPlus配置类* 用于配置MybatisPlus的相关插件*/
@Configuration
public class MybatisPlusConfig {/*** 配置MybatisPlus拦截器* 拦截器用于处理租户、动态表名、分页、乐观锁、非法SQL和防注入攻击等功能** @return 配置好的MybatisPlusInterceptor对象*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 添加租户拦截器,处理多租户场景下的数据隔离interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(/* TenantLineHandler */));// 添加动态表名拦截器,支持动态表名interceptor.addInnerInterceptor(new DynamicTableNameInnerInterceptor(/* DynamicTableNameHandler */));// 添加分页拦截器,实现分页功能interceptor.addInnerInterceptor(new PaginationInnerInterceptor());// 添加乐观锁拦截器,支持乐观锁机制interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());// 添加非法SQL拦截器,防止非法SQL注入interceptor.addInnerInterceptor(new IllegalSQLInnerInterceptor());// 添加防注入攻击拦截器,增强SQL安全性interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());return interceptor;}
}

这里我们以分页插件为里来学习插件的用法。

package com.example.demo.entity;import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;/*** <p>* * </p>** @author * @since 2024-09-08*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("student")
public class Student implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Integer id;private String name;private Integer age;private Integer classId;private String gender;
}
package com.example.demo.mapper;import com.example.demo.entity.Student;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/*** <p>*  Mapper 接口* </p>** @author * @since 2024-09-08*/
public interface StudentMapper extends BaseMapper<Student> {}
package com.example.demo.controller;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.Student;
import com.example.demo.service.impl.StudentServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** <p>*  前端控制器* </p>** @author* @since 2024-09-08*/
@RestController
public class StudentController {@Autowiredprivate StudentServiceImpl studentService;@GetMapping("/students")public Page<Student> getStudentsByAge(@RequestParam int age,@RequestParam(defaultValue = "1") int page,@RequestParam(defaultValue = "10") int size) {return studentService.getStudentsByAge(age, page, size);}
}

启动Spring Boot项目后,访问以下URL进行分页查询:

http://localhost:8080/students?age=17&page=1&size=10

这将返回年龄为17的学生信息,每页10条记录,并以JSON格式返回。

相关文章:

MybatisPlus 快速入门

目录 简介 安装 Spring Boot2 Spring Boot3 Spring 配置 Spring Boot 工程 Spring 工程 常见注解 条件构造器 流式查询 使用示例 批量操作 使用示例 自定义SQL Service接口 CRUD 扩展功能 代码生成 安装插件 通用枚举 配置枚举处理器 插件功能 配置示例…...

Java.lang中的String类和StringBuilder类介绍和常用方法

目录 Java.lang中的String类和StringBuilder类介绍和常用方法 String类介绍 String类的底层成员介绍 基本介绍 回顾String传址调用问题 String类对象的创建方式 String面试题 创建对象or不创建对象 创建了几个对象and共有几个对象 String常用方法 判断字符串是否相等方法 获取字…...

notepad++软件介绍(含安装包)

Notepad 是一款开源的文本编辑器&#xff0c;主要用于编程和代码编辑。它是一个功能强大的替代品&#xff0c;常常被用来替代 Windows 系统自带的记事本。 Notepad win系统免费下载地址 以下是 Notepad 的一些主要特点和功能&#xff1a; 多语言支持&#xff1a;Notepad 支持多…...

chapter13-常用类——(章节小结)——day17

498-常用类阶段梳理...

RTX AI PC 和工作站上部署多样化 AI 应用支持 Multi-LoRA

今天的大型语言模型&#xff08;LLMs&#xff09;在许多用例中都取得了前所未有的成果。然而&#xff0c;由于基础模型的通用性&#xff0c;应用程序开发者通常需要定制和调整这些模型&#xff0c;以便专门针对其用例开展工作。 完全微调需要大量数据和计算基础设施&#xff0…...

C++ STL-deque容器入门详解

1.1 deque容器基本概念 功能&#xff1a; 双端数组&#xff0c;可以对头端进行插入删除操作 deque与vector区别&#xff1a; vector对于头部的插入删除效率低&#xff0c;数据量越大&#xff0c;效率越低deque相对而言&#xff0c;对头部的插入删除速度回比vector快vector访…...

数据结构之折半查找

折半查找&#xff08;Binary Search&#xff09;&#xff0c;也称为二分查找&#xff0c;是一种在有序数组中查找特定元素的搜索算法。其工作原理是&#xff0c;通过不断将待查找的区间分成两半&#xff0c;并判断待查找的元素可能存在于哪一半&#xff0c;然后继续在存在可能性…...

linux高级学习12

24.9.9学习目录 一.条件变量 一.条件变量 通常条件变量和互斥锁同时使用&#xff1b; 条件变量是用来阻塞线程&#xff0c;其本身并不是锁&#xff0c;直到达到特定的要求&#xff1b; &#xff08;1&#xff09;条件变量初始化 #include <pthread.h> int pthread_con…...

leetcode:3174 清除数字 使用栈,时间复杂度O(n)

3174 清除数字 题目链接 题目描述 给你一个字符串 s 。 你的任务是重复以下操作删除 所有 数字字符&#xff1a; 删除 第一个数字字符 以及它左边 最近 的 非数字 字符。 请你返回删除所有数字字符以后剩下的字符串。 示例 1&#xff1a; 输入&#xff1a;s "abc…...

神经网络卷积操作

文章目录 一、nn.Conv2d二、卷积操作原理三、代码实现卷积操作 一、nn.Conv2d nn.Conv2d 是 PyTorch 中的一个类&#xff0c;它代表了一个二维卷积层&#xff0c;通常用于处理图像数据。在深度学习和计算机视觉中&#xff0c;卷积层是构建卷积神经网络&#xff08;CNN&#xf…...

专题二_滑动窗口_算法专题详细总结

目录 滑动窗口&#xff0c;引入&#xff1a; 滑动窗口&#xff0c;本质&#xff1a;就是同向双指针&#xff1b; 1.⻓度最⼩的⼦数组&#xff08;medium&#xff09; 1.解析&#xff1a;给我们一个数组nums&#xff0c;要我们找出最小子数组的和target&#xff0c;首先想到的…...

【机器学习-三-无监督学习】

无监督学习 什么是无监督学习分类聚类降维 有监督和无监督学习的区别 上一节介绍了监督学习&#xff0c;下面来介绍无监督学习&#xff0c;这也是最广泛应用的算法。 什么是无监督学习 上一节中&#xff0c;我们知道了监督学习是通过 对算法&#xff0c;**输入一对数据&#x…...

JAVA基础:Lambda表达式(上)

前言 Lambda表达式是jdk1.8的一个新特性&#xff0c;他属于一种语法堂主要作用是对匿名内部类语法简化 lambda基本应用 lambda表达式想要优化匿名内部类是有前提条件&#xff0c;首先必须是一个接口&#xff0c;而且要求接口中只能有1个抽象方法&#xff0c;称之为函数式接口…...

Vue使用fetch获取本地数据

&#xff08;1&#xff09;使用get test.json文件 { "list":[111,222,333] } <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initi…...

《酒饮真经》秘籍4,让你的酒场技巧更上一层楼!

在酒桌这一独特的舞台上&#xff0c;每个人都扮演着不同的角色&#xff0c;或攻或守&#xff0c;尽显智慧与风度。对于不擅长喝酒的人来说&#xff0c;如何在推杯换盏间既保护自己又不失礼节&#xff0c;是值得我们仔细研究的。下面是酱酒亮哥为您整理的一系列实用的酒桌攻防秘…...

回车符与快捷键记录

一.在Windows和Linux操作系统中&#xff0c;回车符&#xff08;或称为换行符&#xff09;的处理方式区别 1.Windows下的回车符 在Windows系统中&#xff0c;回车符通常是由两个字符组成的序列&#xff1a;回车符&#xff08;Carriage Return&#xff0c;简称CR&#xff0c;AS…...

计算机网络-VRRP工作原理

一、VRRP工作原理 前面我们大概了解了VRRP的一些基础概念&#xff0c;现在开始学习VRRP的技术原理。VRRP的选举及工作步骤&#xff1a; 确定网关地址 选举主备 主设备发送VRRP报文通知Backup设备 主设备响应终端ARP并维持在Master状态 终端正常发送报文到网关进行转发 因为我们…...

6.5椒盐噪声

在OpenCV中联合C给一张图片加上椒盐噪声&#xff08;Salt and Pepper Noise&#xff09;可以通过随机选择像素点并将其置为黑色&#xff08;0&#xff09;或白色&#xff08;255&#xff09;来实现。椒盐噪声是一种随机噪声&#xff0c;通常表现为图像中的孤立黑点&#xff08;…...

CSS样式的引用方式以及选择器使用

1. CSS 引用方式 CSS 可以通过三种方式引用到 HTML 文件中&#xff1a; 行内样式&#xff08;Inline Styles&#xff09;&#xff1a;直接在 HTML 元素中定义样式。内部样式表&#xff08;Internal CSS&#xff09;&#xff1a;在 HTML 文档的 <head> 部分使用 <sty…...

Python Flask_APScheduler定时任务的正确(最佳)使用

描述 APScheduler基于Quartz的一个Python定时任务框架&#xff0c;实现了Quartz的所有功能。最近使用Flask框架使用Flask_APScheduler来做定时任务&#xff0c;在使用过程当中也遇到很多问题&#xff0c;例如在定时任务调用的方法中需要用到flask的app.app_context()时&#…...

Linux命名管道

​ ​通信的前提是让不同的进程看到同一份资源&#xff0c;因为路径是具有唯一性的&#xff0c;所以我们可以使用路径文件名来唯一的让不同进程看到同一份资源&#xff0c;实现没有血缘关系的两个进程进行管道通信 1.指令级 mkfifio&#xff08;FILENAME,0666&#xff09; …...

Xinstall助力App全渠道统计,参数传递下载提升用户体验!

在移动互联网时代&#xff0c;App已成为我们日常生活中不可或缺的一部分。然而&#xff0c;对于App开发者来说&#xff0c;如何有效地推广和运营自己的应用&#xff0c;却是一个不小的挑战。尤其是在面对众多渠道、复杂的数据统计和用户需求多样化的情况下&#xff0c;如何精准…...

【时时三省】(C语言基础)指针进阶 例题4

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 strlen是求字符串长度 这个需要算上&#xff3c;0 第一个arr 是打印6 因为它加上&#xff3c;0是有六个元素 第二个arr0 数组名相当于首元素的地址 a的地址加0还是a的地址 所以这个地方还是…...

k8s的配置管理

一、配置管理分为两种&#xff1a; 1. 加密配置&#xff1a;用来保存密码和token密钥对以及其它敏感的k8s资源。 2.应用配置&#xff1a;我们需要定制化的给应用进行配置&#xff0c;我们需要把定制好的配置文件同步到pod当中的容器。 二、加密配置 1.secret三种类型&#xf…...

JAVA- 多线程

一&#xff0c;多线程的概念 1.并行与并发 并行&#xff1a;多个任务在同一时刻在cpu 上同时执行并发&#xff1a;多个任务在同一时刻在cpu 上交替执行 2.进程与线程 进程&#xff1a;就是操作系统中正在运行的一个应用程序。所以进程也就是“正在进行的程序”。&#xff0…...

【Qt】解决设置QPlainTextEdit控件的Tab为4个空格

前言 PyQt5 是一个用于创建跨平台桌面应用程序的 Python 绑定集合&#xff0c;它提供了对 Qt 应用程序框架的访问。用于开发具有图形用户界面&#xff08;GUI&#xff09;的应用程序&#xff0c;以及非GUI程序。PyQt5 使得 Python 开发者可以使用 Qt 的丰富功能来构建应用程序。…...

elementUI根据列表id进行列合并@莫成尘

本文章提供了elementUI根据列表id进行列合并的demo&#xff0c;效果如图&#xff08;可直接复制代码粘贴&#xff09; <template><div id"app"><el-table border :data"tableList" style"width: 100%" :span-method"objectS…...

基于人工智能的智能安防监控系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据采集与预处理模型训练与预测实时监控与检测应用场景结论 1. 引言 随着科技的发展&#xff0c;智能安防监控系统逐渐成为家庭、企业和公共场所保障安全的核心工具。通过人工智能和计…...

分享从零开始学习网络设备配置--任务6.3 使用基本ACL限制网络访问

任务描述 某公司构建了互联互通的办公网&#xff0c;为保护公司内网用户数据的安全&#xff0c;该公司实施内网安全防范措施。公司分为经理部、财务部和销售部&#xff0c;分属3个不同的网段&#xff0c;3个部门之间用路由器进行信息传递。为了安全起见&#xff0c;公司领导要求…...

数据结构——线性表(静态链表、循环链表以及双向链表)

1、静态链表 用数组描述的链表叫做静态链表&#xff0c;这种描述方法叫做游标实现法。 静态链表需要对数组的第一个和最后一个元素作为特殊元素处理&#xff0c;不存数据。 最后一个指向第一个有数据的下标地址&#xff0c;第一个游标指向第一个没有数据的下标地址。 我们对…...