前言
在上一篇文章从零开始配置MybatisPlus(一)中,讲解了如何配置整合MybatisPlus和Spring Boot并调用了MybatisPlus原生方法。这篇文文章将会介绍一些自己在使用MybatisPlus开发时的一些经验和碰到的一些坑。
MybatisPlus常用原生方法简介
在这里仅讨论Service中的CRUD接口,因为实际开发中你需要关心Mapper方法的情况并不多,仅在重写Service和
重写xml时会涉及到Mapper,这两方面的内容在下文再进行相关讲解。
MybatisPlus Service接口官方文档
其中最常用的一些接口:
- save,新增记录,入参为实体类对象
- updateById 通过主键修改内容,入参为实体类对象,对象需要包含主键字段(注:关于主键,在自动生成的实体类中主键会被@TableId主键标注并映射到数据库字段上,下文不再详述)
- selectById 通过主键查询内容,入参为主键id;也可直接传入实体类对象,对象需要包含主键字段
- removeById 通过主键删除内容,入参为主键id;也可直接传入实体类对象,对象需要包含主键字段
- list 入参为Wrapper条件构造器,下文将会详细介绍,可不传入参,即获取该表所有的数据
- page 入参为IPage对象和Wrapper条件构造器,条件构造器可不传
使用分页语句需要提前配置好MybatisPlus分页插件:
//Spring boot方式
@EnableTransactionManagement
@Configuration
@MapperScan("com.baomidou.cloud.service.*.mapper*")
public class MybatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// paginationInterceptor.setLimit(你的最大单页限制数量,默认 500 条,小于 0 如 -1 不受限制);
return paginationInterceptor;
}
}
如何声明IPage对象:Object为实体类
Page<Object> page=new Page<>(1,10);
使用原生方法的一些要点
- 在使用update、updateById方法时,你传入的对象中,为null的字段是不会进行修改的,如果需要在修改时无论是否为null都改动该字段,需要在字段上使用注解:@TableField(fill = FieldFill.UPDATE)
- saveBatch和removeByIds的方法是附带事务管理的,如果其中有一条失败了,之前添加/删除的会进行回滚
- update、page、list的Wrapper不是必要的入参,但delete的Wrapper是必要入参
- 使用原生的方法时不需要自定义namespace,但是如果在表的实体类中新增了不属于该表的字段,需要在该字段上添加注解:@TableField(exist = false) 用来标明该字段不属于此实体类对应的表,否则在调用原生的list、page方法时,MybatisPlus的自动映射会报错
原生方法重写
有时候原生的方法可能无法满足开发需求了,就需要重写;
重写Service方法只需要在Serviceimpl类中构造一个同名同入参的方法即可
@Service
public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements IAreaService {
@Resource
private AreaMapper areaMapper;
public boolean save(Area area){
System.out.println("添加方法重写");
int result=areaMapper.insert(area);
if(result>0){
return true;
}
return false;
}
}
而重写mapper则需要重写对应的xml,在xml中编写id为mapper方法名的mybatis语句:一般来说在表的原字段已经不能满足需求,需要通过表关联获取别的字段时就需要使用mapper的重写:
重写分页方法
<select id="selectPage" resultType="com.example.demo.sys.entity.Area">
select a.*,b.user_name from sys_area a
left join user b on a.user_id=b.user_id
<where>
${ew.sqlSegment}
</where>
</select>
重写后需要在实体类中新增userName字段并添加@TableField(exist = false)注解,不需要其他操作;
其中${ew.sqlSegment}为Wrapper条件构造器中的内容,下文详述。
条件构造器:Wrapper
Wrapper是MybatisPlus用来构造条件的,当MybatisPlus已有的原生方法无法满足开发时的查询需求时,你可以在不重写原生方法的情况下使用Wrapper来构造搜索条件。在开发过程中,笔者都是用的QueryWrapper来进行的开发。
首先声明QueryWrapper对象:Object为实体类
QueryWrapper<Object> queryWrapper=new QueryWrapper<>();
然后使用QueryWrapper对象构造条件
queryWrapper.eq("area_name","上海");
该语句实质即为:area_name=‘上海’;构造条件后会在Sql语句中的where后附带此条件
常用的还有:
queryWrapper.like("area_name","123");
queryWrapper.between("add_time",beginTime,endTime);
当然,这种方法并不太优雅,所以MybatisPlus提供了另外一种方式来供我们构造条件:
QueryWrapper<Area> queryWrapper=new QueryWrapper<>();
queryWrapper.lambda().eq(Area::getAreaName,"上海");
第二行语句与上面的eq语句等同,实质为Area类中的字段areaName映射到数据库字段area_name
但此方法有一个缺陷:使用此方法的字段是不能附带表的别名的,在上述重写分页方法的情况下,对userId该字段使用lambda()时:
queryWrapper.lambda().eq(Area::getUserId,1);
重写分页方法
<select id="selectPage" resultType="com.example.demo.sys.entity.Area">
select a.*,b.user_name from sys_area a
left join user b on a.user_id=b.user_id
<where>
${ew.sqlSegment}
</where>
</select>
此时调用分页接口会报错,因为此时sql的条件语句中会因为不知道user_id是哪张表的字段而报错,所以建议如果重写了MybatisPlus的原生方法,使用普通的语句:
queryWrapper.eq("a.user_id",1);
至此,MybatisPlus方法的基础使用就介绍完了