Mybatis-Plus
MyBatis-Plus(简称 MP)是一个MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。其突出的特性如下:
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,提供了大量的通用的CRUD方法,因此可以省去大量手写sql的语句的工作。
- 条件构造器:提供了强大的条件构造器,可以构造各种复杂的查询条件,以应对各种复杂查询。
- 内置分页插件:配置好插件之后,写分页等同于普通 List 查询,无需关注分页逻辑。
Mybatis Plus与SpringBoot的集成
引入Maven 依赖
提前创建好一个SpringBoot项目,然后在项目中引入MyBatis Plus依赖
<!--springboot2-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.6</version>
</dependency>
<!--springboot3-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.7</version>
</dependency>
配置application.yml
文件
#springboot整合mybatisPlus
mybatis-plus:
#配置别名包
#MyBatis 在启动时会扫描该包下的所有类,并为其中的每个类创建一个别名。例如,如果我们有一个 com.example.model.User 的 #类,MyBatis 会为其自动创建一个别名 User。
#用于自动扫描指定包路径下的类,并为这些类创建别名
type-aliases-package: com.chs.pojo
#加载指定位置的映射文件
mapper-locations: classpath:/mapper/*.xml
configuration:
#开启驼峰映射规则
map-underscore-to-camel-case: true
#添加操作日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
实体类配置
@Data
//表中的user表数据于当前User类绑定
@TableName("user")
public class User {
//主键自增,并于数据库中id字段绑定
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@TableField("name")
private String name;
@TableField("age")
private Integer age;
//当数据库字段名和实体类数据名一致时,可以不用写@TableField(value = "age")。
@TableField("email")
private String email;
}
注解知识点:
实体类中的三个注解的含义如下
-
@TableName
:表名注解,用于标识实体类所对应的表value
:用于声明表名
-
@TableId
:主键注解,用于标识主键字段value
:用于声明主键的字段名type
:用于声明主键的生成策略,常用的策略有AUTO
、ASSIGN_UUID
、INPUT
等等
-
@TableField
:普通字段注解,用于标识属性所对应的表字段value
:用于声明普通字段的字段名
通用Mapper
通用Mapper提供了通用的CRUD方法,使用它可以省去大量编写简单重复的SQL语句的工作,具体用法如下
创建Mapper接口
创建UserMapper
接口,并继承由Mybatis Plus提供的BaseMapper<T>
接口,如下
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
知识点:若Mapper接口过多,可不用逐一配置@Mapper
注解,而使用@MapperScan
注解指定包扫描路径进行统一管理,例如
@SpringBootApplication
@MapperScan("com.atguigu.hellomp.mapper")
public class HelloMpApplication {
public static void main(String[] args) {
SpringApplication.run(HelloMpApplication.class, args);
}
}
常用使用方法mapper层
添加数据
//【添加数据:(增)】
int insert(T entity); // 插入一条记录
List<BatchResult> insert(Collection<T> entityList); //批量插入多条数据
注:
T 表示任意实体类型
entity 表示实体对象
insert 后主键会自动 set 到实体的 ID 字段 所以后面你只需要 getld() 就好
删除数据
//【删除数据:(删)】
int deleteById(Serializable id); // 根据主键 ID 删除
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); // 根据 map 定义字段的条件删除
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper); // 根据实体类定义的 条件删除对象
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); // 进行批量删除
注:
id 表示 主键 ID
columnMap 表示表字段的 map 对象
wrapper 表示实体对象封装操作类,可以为 null。
idList 表示 主键 ID 集合(列表、数组),不能为 null 或 empty
修改数据
//【修改数据:(改)】
int updateById(@Param(Constants.ENTITY) T entity); // 根据 ID 修改实体对象。
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper); // 根据 updateWrapper 条件修改实体对象
注:
update 中的 entity 为 set 条件,可以为 null。
updateWrapper 表示实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
查询数据
//【查询数据:(查)】
T selectById(Serializable id); // 根据 主键 ID 查询数据
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); // 进行批量查询
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); // 根据表字段条件查询
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 根据实体类封装对象 查询一条记录
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询记录的总条数
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(返回 entity 集合)
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(返回 map 集合)
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(但只保存第一个字段的值)
<E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(返回 entity 集合),分页
<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(返回 map 集合),分页
注:
queryWrapper 表示实体对象封装操作类(可以为 null)
page 表示分页查询条件
测试常用方法Mapper
创建userMapperTest
测试类型,内容如下
@SpringBootTest
class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectList() {
//获取所有用户
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
@Test
public void testSelectById() {
//根据id获取用户
User user = userMapper.selectById(1);
System.out.println(user);
}
@Test
//插入用户
public void testInsert() {
User user = new User();
user.setName("zhangsan");
user.setAge(11);
user.setEmail("[email protected]");
userMapper.insert(user);
}
@Test
//根据id修改用户
public void testUpdateById() {
User user = userMapper.selectById(1);
user.setName("xiaoming");
userMapper.updateById(user);
}
@Test
//根据id删除用户
public void testDeleteById() {
userMapper.deleteById(1);
}
}
通用Service
通用Service进一步封装了通用Mapper的CRUD方法,并提供了例如saveOrUpdate
、saveBatch
等高级方法。
创建Service接口
创建UserService
,内容如下
public interface UserService extends IService<User> {
}
创建Service实现类
创建UserServiceImpl
,内容如下
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
常用使用方法Service层
添加数据
//【添加数据:(增)】
default boolean save(T entity); // 调用 BaseMapper 的 insert 方法,用于添加一条数据。
boolean saveBatch(Collection<T> entityList, int batchSize); // 批量插入数据
注:
entityList 表示实体对象集合
batchSize 表示一次批量插入的数据量,默认为 1000
修改或添加数据
//【添加或修改数据:(增或改)】
boolean saveOrUpdate(T entity); // id 若存在,则修改, id 不存在则新增数据
default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper); // 先根据条件尝试更新,然后再执行 saveOrUpdate 操作
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize); // 批量插入并修改数据
删除数据
//【删除数据:(删)】
default boolean removeById(Serializable id); // 调用 BaseMapper 的 deleteById 方法,根据 id 删除数据。
default boolean removeByMap(Map<String, Object> columnMap); // 调用 BaseMapper 的 deleteByMap 方法,根据 map 定义字段的条件删除
default boolean remove(Wrapper<T> queryWrapper); // 调用 BaseMapper 的 delete 方法,根据实体类定义的 条件删除对象。
default boolean removeByIds(Collection<? extends Serializable> idList); // 用 BaseMapper 的 deleteBatchIds 方法, 进行批量删除。
修改数据
//【修改数据:(改)】
default boolean updateById(T entity); // 调用 BaseMapper 的 updateById 方法,根据 ID 选择修改。
default boolean update(T entity, Wrapper<T> updateWrapper); // 调用 BaseMapper 的 update 方法,根据 updateWrapper 条件修改实体对象。
boolean updateBatchById(Collection<T> entityList, int batchSize); // 批量更新数据
查询数据
//【查找数据:(查)】
default T getById(Serializable id); // 调用 BaseMapper 的 selectById 方法,根据 主键 ID 返回数据。
default List<T> listByIds(Collection<? extends Serializable> idList); // 调用 BaseMapper 的 selectBatchIds 方法,批量查询数据。
default List<T> listByMap(Map<String, Object> columnMap); // 调用 BaseMapper 的 selectByMap 方法,根据表字段条件查询。
default T getOne(Wrapper<T> queryWrapper); // 返回一条记录(实体类保存)。
Map<String, Object> getMap(Wrapper<T> queryWrapper); // 返回一条记录(map 保存)。
default int count(Wrapper<T> queryWrapper); // 根据条件返回 记录数。
default List<T> list(); // 返回所有数据。
default List<T> list(Wrapper<T> queryWrapper); // 调用 BaseMapper 的 selectList 方法,查询所有记录(返回 entity 集合)。
default List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper); // 调用 BaseMapper 的 selectMaps 方法,查询所有记录(返回 map 集合)。
default List<Object> listObjs(); // 返回全部记录,但只返回第一个字段的值。
default <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper); // 调用 BaseMapper 的 selectPage 方法,分页查询。
default <E extends IPage<Map<String, Object>>> E pageMaps(E page, Wrapper<T> queryWrapper); // 调用BaseMapper 的 selectMapsPage 方法,分页查询。
注:
get 用于返回一条记录。
list 用于返回多条记录。
count 用于返回记录总数。
page 用于分页查询。
【链式调用:】
default QueryChainWrapper<T> query(); // 普通链式查询
default LambdaQueryChainWrapper<T> lambdaQuery(); // 支持 Lambda 表达式的修改
default UpdateChainWrapper<T> update(); // 普通链式修改
default LambdaUpdateChainWrapper<T> lambdaUpdate(); // 支持 Lambda 表达式的修改
注:
query 表示查询
update 表示修改
Lambda 表示内部支持 Lambda 写法。
形如:
query().eq("column", value).one();
lambdaQuery().eq(Entity::getId, value).list();
update().eq("column", value).remove();
lambdaUpdate().eq(Entity::getId, value).update(entity);
测试使用方法Service
创建UserServiceImplTest
测试类,内容如下
@SpringBootTest
class UserServiceImplTest {
@Autowired
private UserService userService;
@Test
public void testSaveOrUpdate() {
//根据id查询用户
User user1 = userService.getById(2);
user1.setName("xiaohu");
User user2 = new User();
user2.setName("lisi");
user2.setAge(27);
user2.setEmail("[email protected]");
//保存或更新用户
userService.saveOrUpdate(user1);
userService.saveOrUpdate(user2);
}
@Test
public void testSaveBatch() {
User user1 = new User();
user1.setName("dongdong");
user1.setAge(49);
user1.setEmail("[email protected]");
User user2 = new User();
user2.setName("nannan");
user2.setAge(29);
user2.setEmail("[email protected]");
List<User> users = List.of(user1, user2);
//批量插入用户
userService.saveBatch(users);
}
}
条件构造器
在 MyBatis-Plus 中,Wrapper 类是构建查询和更新条件的核心工具。
-
QueryWrapper:专门用于构造查询条件,支持基本的等于(eq)、不等于(ne)、大于(gt)、小于(lt)等各种常见操作。它允许你以链式调用的方式添加多个查询条件,并且可以组合使用
and
和or
逻辑。 -
UpdateWrapper:用于构造更新条件,可以在更新数据时指定条件。与 QueryWrapper 类似,它也支持链式调用和逻辑组合。使用 UpdateWrapper 可以在不创建实体对象的情况下,直接设置更新字段和条件。
-
LambdaQueryWrapper:这是一个基于 Lambda 表达式的查询条件构造器,它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名。这种方式提高了代码的可读性和可维护性,尤其是在字段名可能发生变化的情况下。
-
LambdaUpdateWrapper:类似于 LambdaQueryWrapper,LambdaUpdateWrapper 是基于 Lambda 表达式的更新条件构造器。它允许你使用 Lambda 表达式来指定更新字段和条件,同样避免了硬编码字段名的问题。
常用条件
比较大小
//【比较大小: ( =, <>, >, >=, <, <= )】
eq(R column, Object val); // 等价于 =
eq(condition...,R column, object val) //当条件满足为true,拼接后面where
ne(R column, Object val); // 等价于 <>
gt(R column, Object val); // 等价于 >
ge(R column, Object val); // 等价于 >=
lt(R column, Object val); // 等价于 <
le(R column, Object val); // 等价于 <=
//例:
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("name", "chs") ---> name = 'chs'
范围
//【范围:(between、not between、in、not in)】
between(R column, Object val1, Object val2); // 等价于 between a and b
notBetween(R column, Object val1, Object val2); // 等价于 not between a and b
in(R column, Object... values); // 等价于 字段 IN (v0, v1, ...)
notIn(R column, Object... values); // 等价于 字段 NOT IN (v0, v1, ...)
inSql(R column, Object... values); // 等价于 字段 IN (sql 语句),
//例: inSql("id", "select id from table where id < 3") ---> id in (select id from table where id < 3)
notInSql(R column, Object... values); // 等价于 字段 NOT IN (sql 语句)
模糊匹配
//【模糊匹配:(like)】
like(R column, Object val); // 等价于 LIKE '%值%'
notLike(R column, Object val); // 等价于 NOT LIKE '%值%'
likeLeft(R column, Object val); // 等价于 LIKE '%值'
likeRight(R column, Object val); // 等价于 LIKE '值%'
空值比较
【空值比较:(isNull、isNotNull)】
isNull(R column); // 等价于 IS NULL
isNotNull(R column); // 等价于 IS NOT NULL
分组排序
//【分组、排序:(group、having、order)】
groupBy(R... columns); // 等价于 GROUP BY 字段, ...
orderByAsc(R... columns); // 等价于 ORDER BY 字段, ... ASC(升序--小到大)
orderByDesc(R... columns); // 等价于 ORDER BY 字段, ... DESC(降序--大到小)
having(String sqlHaving, Object... params); // 等价于 HAVING ( sql语句 )
拼接、嵌套sql
//【拼接、嵌套 sql:(or、and、nested、apply)】
or(); // 等价于 a or b, 例:eq("id",1).or().eq("name","chs") ---> id = 1 or name = 'chs'
or(Consumer<Param> consumer); // 等价于 or(a or/and b),or 嵌套。
//例: or(i -> i.eq("name", "李白").ne("status", "活着")) ---> or (name = '李白' and status <> '活着')
and(Consumer<Param> consumer); // 等价于 and(a or/and b),and 嵌套。
//例: and(i -> i.eq("name", "李白").ne("status", "活着")) ---> and (name = '李白' and status <> '活着')
nested(Consumer<Param> consumer); // 等价于 (a or/and b),普通嵌套。
apply(String applySql, Object... params); // 拼接sql(若不使用 params 参数,可能存在 sql 注入),
//例: apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08") ---> date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
last(String lastSql); // 无视优化规则直接拼接到 sql 的最后,可能存若在 sql 注入。
exists(String existsSql); // 拼接 exists 语句。例: exists("select id from table where age = 1")
条件
【QueryWrapper 条件:】
select(String... sqlSelect); // 用于定义需要返回的字段。
//例: select("id", "name", "age") ---> select id, name, age
select(Predicate<TableFieldInfo> predicate); // Lambda 表达式,过滤需要的字段。
lambda(); // 返回一个 LambdaQueryWrapper
【UpdateWrapper 条件:】
set(String column, Object val); // 用于设置 set 字段值。例: set("name", null) ---> set name = null
etSql(String sql); // 用于设置 set 字段值。例: setSql("name = '老李头'") ---> set name = '老李头'
lambda(); // 返回一个 LambdaUpdateWrapper```
例:QueryWrapper
@Test
public void testQueryWrapper() {
// Step1:创建一个 QueryWrapper 对象
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
// Step2: 构造查询条件
queryWrapper
.select("id", "name", "age") //指定需要返回的字段
.eq("age", 20)
.like("name", "j");
// Step3:执行查询
userService
.list(queryWrapper)
.forEach(System.out::println);
}
测试wrapper
@SpringBootTest
public class WrapperTest {
@Autowired
private UserService userService;
//查询条件
@Test
public void testQueryWrapper() {
//查询name=Tom的所有用户
QueryWrapper<User> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.eq("name", "Tom");
//查询邮箱域名为baomidou.com的所有用户
QueryWrapper<User> queryWrapper2 = new QueryWrapper<>();
queryWrapper2.like("email", "baomidou.com");
//查询所有用户信息并按照age字段降序排序
QueryWrapper<User> queryWrapper3 = new QueryWrapper<>();
queryWrapper3.orderByDesc("age");
//查询age介于[20,30]的所有用户
QueryWrapper<User> queryWrapper4 = new QueryWrapper<>();
queryWrapper4.between("age", 20, 30);
//查询age小于20或大于30的用户
QueryWrapper<User> queryWrapper5 = new QueryWrapper<>();
queryWrapper5.lt("age", 20).or().gt("age", 30);
//邮箱域名为baomidou.com且年龄小于30或大于40且的用户
QueryWrapper<User> queryWrapper6 = new QueryWrapper<>();
queryWrapper6.like("email", "baomidou.com").and(wrapper -> wrapper.lt("age", 30).or().gt("age", 40));
List<User> list = userService.list(queryWrapper6);
list.forEach(System.out::println);
}
//更新条件
@Test
public void testUpdateWrapper() {
//将name=Tom的用户的email改为[email protected]
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name", "Tom");
updateWrapper.set("email", "[email protected]");
userService.update(updateWrapper);
}
}
测试LambdaWrapper
上述的
QueryWrapper
和UpdateWrapper
均有一个Lambda
版本,也就是LambdaQueryWrapper
和LambdaUpdateWrapper
,Lambda
版本的优势在于,可以省去字段名的硬编码。
@SpringBootTest
public class LambdaWrapperTest {
@Autowired
private UserService userService;
//查询条件
@Test
public void testLambdaQueryWrapper() {
//查询name=Tom的所有用户
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getName, "Tom");
List<User> list = userService.list(lambdaQueryWrapper);
list.forEach(System.out::println);
}
//更新条件
@Test
public void testLambdaUpdateWrapper() {
//将name=Tom的用户的邮箱改为[email protected]
LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.eq(User::getName, "Tom");
lambdaUpdateWrapper.set(User::getEmail, "[email protected]");
userService.update(lambdaUpdateWrapper);
}
}
逻辑删除
逻辑删除,可以方便地实现对数据库记录的逻辑删除而不是物理删除。逻辑删除是指通过更改记录的状态或添加标记字段来模拟删除操作,从而保留了删除前的数据,便于后续的数据分析和恢复。
- 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据
- 逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
数据库和实体类添加逻辑删除字段
表添加逻辑删除字段,可以是一个布尔类型、整数类型或枚举类型。
ALTER TABLE USER ADD deleted INT DEFAULT 0 ; # int 类型 1 逻辑删除 0 未逻辑删除
实体类添加属性
@Data
public class User {
private Integer id;
private String name;
private Integer age;
private String email;
private Integer deleted; //逻辑删除字段
}
指定逻辑删除字段和属性值
单一指定
@Data
public class User {
private Integer id;
private String name;
private Integer age;
private String email;
@TableLogic
//逻辑删除字段 int mybatis-plus下,默认 逻辑删除值为1 未逻辑删除 0
private Integer deleted;
}
全局配置
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
注意:==>逻辑删除以后,没有真正的删除语句,删除改为修改语句!
自动填充字段
MyBatis-Plus 提供了一个便捷的自动填充功能,用于在插入或更新数据时自动填充某些字段,如创建时间、更新时间等。以下是如何使用这一功能的详细说明。
定义实体类
在实体类中,你需要使用 @TableField
注解来标记哪些字段需要自动填充,并指定填充的策略。
public class User {
@TableField(fill = FieldFill.INSERT)
private String createTime;
@TableField(fill = FieldFill.UPDATE)
private String updateTime1;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Date updateTime2;
// 其他字段...
}
实现 MetaObjectHandler
创建一个类来实现 MetaObjectHandler
接口,并重写 insertFill
和 updateFill
方法。
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 自定义插入时填充规则
*/
@Override
public void insertFill(MetaObject metaObject) {
log.info("开始插入填充...");
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictUpdateFill(metaObject, "updateTime2", LocalDateTime.class, LocalDateTime.now());
}
/**
* 自定义更新时填充规则
*/
@Override
public void updateFill(MetaObject metaObject) {
log.info("开始更新填充...");
this.strictUpdateFill(metaObject, "updateTime1", LocalDateTime.class, LocalDateTime.now());
}
}
注意:确保你的
MyMetaObjectHandler
类被 Spring 管理,可以通过@Component
或@Bean
注解来实现。
其他注意事项
字段类型: 确保数据库中的 createTime 和 updateTime 字段类型与 Java 实体类中的类型相匹配(通常是 DATETIME 类型)。
时间格式: 如果需要统一时间格式,可以在配置文件中设置 Spring Boot 的全局时间格式,或使用 @JsonFormat 注解指定序列化时的格式。
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
分页插件
分页查询是一个很常见的需求,故Mybatis-Plus提供了一个分页插件,使用它可以十分方便的完成分页查询。下面介绍Mybatis-Plus分页插件的用法,详细信息可参考[官方文档](分页插件 | MyBatis-Plus (baomidou.com))。
配置分页插件
创建com.atguigu.hellomp.config.MPConfiguration
配置类,增加如下内容
@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {
/**
* 添加分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 如果配置多个插件, 切记分页最后添加
// 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
return interceptor;
}
}
分页插件使用说明
Page 类
Page
类继承了 IPage
类,实现了简单分页模型。如果你需要实现自己的分页模型,可以继承 Page
类或实现 IPage
类。
属性名 | 类型 | 默认值 | 描述 |
---|---|---|---|
records | List |
emptyList | 查询数据列表 |
total | Long | 0 | 查询列表总记录数 |
size | Long | 10 | 每页显示条数,默认 10 |
current | Long | 1 | 当前页 |
orders | List |
emptyList | 排序字段信息 |
optimizeCountSql | boolean | true | 自动优化 COUNT SQL |
optimizeJoinOfCountSql | boolean | true | 自动优化 COUNT SQL 是否把 join 查询部分移除 |
searchCount | boolean | true | 是否进行 count 查询 |
maxLimit | Long | 单页分页条数限制 | |
countId | String | XML 自定义 count 查询的 statementId |
分页对象既作为分页查询的参数,也作为分页查询的返回结果,当作为查询参数时,通常只需提供current
和size
属性,如下
IPage<T> page = new Page<>(current, size);
注:IPage
为分页接口,Page
为IPage
接口的一个实现类。
分页查询
Mybatis Plus的BaseMapper
和ServiceImpl
均提供了常用的分页查询的方法,例如:
BaseMapper
的分页查询:
IPage<T> selectPage(IPage<T> page,Wrapper<T> queryWrapper);
ServiceImpl
的分页查询:
// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
自定义Mapper
对于自定义SQL,也可以十分方便的完成分页查询,如下
Mapper
接口:
IPage<UserVo> selectPageVo(IPage<?> page, Integer state);
Mapper.xml
:
<select id="selectPageVo" resultType="xxx.xxx.xxx.UserVo">
SELECT id,name FROM user WHERE state=#{state}
</select>
注意:Mapper.xml
中的SQL只需实现查询list
的逻辑即可,无需关注分页的逻辑。
分页查询测试
@SpringBootTest
public class PageTest {
@Autowired
private UserService userService;
@Autowired
private UserMapper userMapper;
//通用Service分页查询
@Test
public void testPageService() {
Page<User> page = new Page<>(2, 3);
Page<User> userPage = userService.page(page);
userPage.getRecords().forEach(System.out::println);
}
//通用Mapper分页查询
@Test
public void testPageMapper() {
IPage<User> page = new Page<>(2, 3);
IPage<User> userPage = userMapper.selectPage(page, null);
userPage.getRecords().forEach(System.out::println);
}
//---------------------------------------------------------------------------
//自定义SQL分页查询
@Test
public void testCustomMapper() {
IPage<User> page = new Page<>(2, 3);
IPage<User> userPage = userMapper.selectUserPage(page);
userPage.getRecords().forEach(System.out::println);
}
}
在UserMapper中声明分页查询方法如下
IPage<User> selectUserPage(IPage<User> page);
创建resources/mapper/UserMapper.xml
文件,内容如下
<?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.atguigu.hellomp.mapper.UserMapper">
<select id="selectUserPage" resultType="com.atguigu.hellomp.entity.User">
select *
from user
</select>
</mapper>
注意:
Mybatis-Plus中Mapper.xml
文件路径默认为:classpath*:/mapper/**/*.xml
,可在application.yml
中配置以下参数进行修改
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
MyBatisX插件
MyBatis Plus提供了一个IDEA插件——MybatisX
,使用它可根据数据库快速生成Entity
、Mapper
、Mapper.xml
、Service
、ServiceImpl
等代码,使用户更专注于业务。
安装插件
在IDEA插件市场搜索MyBatisX
,进行在线安装
配置数据库连接
在IDEA中配置数据库连接
生成代码
首先将之前编写的User
、UserMapper
、UserServcie
、UserServiceImpl
全部删除,然后按照下图指示使用插件生成代码
配置实体类相关信息
配置代码模版信息
点击Finish然后查看生成的代码。
标签:分页,删除,public,plus,mybatis,查询,id,name From: https://www.cnblogs.com/21CHS/p/18430655