上篇文章讲述了如何通过一个数据库完成代码的自动生成,包括接口,xml等相关文件,同时还配置了swagger的相关信息,本篇将讲述如何利用mybatis-plus完成一个完美的crud,只涉及数据的更改,不考虑其他任何情况。相信你看了此篇文章肯定可以彻底解放你写sql的烦恼。需要说明的是,一些公司可能禁止使用封装,但是也有公司推从封装,从简而行,快速开发,笔者公司的项目90%采用的都是该框架。
在进行crud的操作之前,需了解一些mybatis-plus的表达式(lambda)的含义,这些表达式是构造条件查询的以及更新数据的根本,这个作为写代码的一些参考,无需刻意记忆。
之所以是单表操作,我们把自动生成的实体类属性当成数据库的字段,用代码就行构造一个查询或者更新。抓住此条思路,理解表达式的构造会简单一点。本篇代码仓库上传地址:https://github.com/DaYuanHou/studyMybatis-plus.git
条件参数说明
查询方式 | 说明 |
---|---|
eq | 等于= |
allEq | 基于 map 内容等于= |
ne | 不等于<> |
gt | 大于> |
ge | 大于等于>= |
lt | 小于< |
le | 小于等于<= |
like | 模糊查询 LIKE(包含左前缀查询,后右前缀查询) |
notLike | 模糊查询 NOT LIKE |
in | IN 查询 |
notIn | NOT IN 查询 |
isNull | NULL 值查询 |
isNotNull | IS NOT NULL |
groupBy | 分组 GROUP BY |
having | HAVING 关键词 |
orderBy | 排序 ORDER BY |
orderAsc | ASC 排序 ORDER BY |
orderDesc | DESC 排序 ORDER BY |
exists | EXISTS 条件语句 |
notExists | NOT EXISTS 条件语句 |
between | BETWEEN 条件语句 |
notBetween | NOT BETWEEN 条件语句 |
addFilter | 自由拼接 SQL |
last | 拼接在最后,例如:last("LIMIT 1")避免出现select one but found 2的异常 |
- 一项目的基本结构和表结构(建表的sql上篇sql)
表字段
以下全部为自动生成的内容。
数据库实体类包含lombok,swagger的标签
项目的大致结构
- 二 各种CRUD的例子(其中最为重要的就是baseMapper这个对象,条件构造器,更新构造器)需要说明的是,正常的开发逻辑层应该是service处理。在对应的逻辑层直接使用baseMapper即可完成对应的表格操作。笔者这里是通过controller层的注入service 获取的baseMapper。不是太规范,但是大家能知道意思就可以了。并且我在上篇文章中已经提到过打印出sql执行的语句,方便我们查看mybatis-plus的执行过程。如下图所示为正规的项目代码结构。
- 数据的入库操作
传人的是一个对象,如果传人的是字段的话,你需要new 一个对象,把属性值放入到对象中(如createTime)。两个效果一样,为了方便讲述,笔者采用对象的方式。建议实际开发采用相关字段或者封装好的DTO,swaager的入参图。
@Autowired
private ITestPlusService testPlusService;
@PostMapping("/add")
public String addData(TestPlus testPlus) {
testPlus.setCreateTime(LocalDateTime.now());
BaseMapper<TestPlus> baseMapper = testPlusService.getBaseMapper();
int insert = baseMapper.insert(testPlus);
if(insert==1) return "成功";
else return "error";
}
如上就是一个简单的插入操作,我没有写任何的sql。只是注入了自动生成的代码ITestPlusService获得baseMapper对象,通过baseMapper对数据库进行操作。
我们来看下实际的效果吧,我随便传人一个数据。数据显示的数据
2.数据库的更新操作,其中重要的对象为UpdateWrapper,这个mybatis-plus的更新条件构造器。
@PostMapping("/update")
public String update(TestPlus testPlus) {
BaseMapper<TestPlus> baseMapper = testPlusService.getBaseMapper();
int update = 0;
// 将对应的Id数据的年龄更为44岁,同时创建时间也进行修改
update = baseMapper.update(testPlus, new UpdateWrapper<TestPlus>()
.lambda().eq(TestPlus::getId, testPlus.getId())
.set(TestPlus::getAge, 44)
.set(TestPlus::getCreateTime, LocalDateTime.now()));
// 直接调用封装好的根据id更新,将修改的数据进行更新,不修的数据会保持原有状态。
update = baseMapper.updateById(testPlus);
if (update == 1) return "成功";
else return "error";
}
打印的sql如下所示
3.删除数据
@PostMapping("/delete")
// 全部为硬删除。
public String delete(TestPlus testPlus) {
// 删除id为1的数据。
BaseMapper<TestPlus> baseMapper = testPlusService.getBaseMapper();
int i = baseMapper.deleteById(1);
// 通过id的集合删除,
// baseMapper.deleteBatchIds(new ArrayList<>());
if (i == 1) return "成功";
else return "error";
}
4.分页查询数据,具体的解释包含在对应的注释中,分页之前需要配置分页。如下所示的分页配置
@EnableTransactionManagement
@Configuration
@MapperScan("com.mybaitisplus.demo.mapper")
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
下面为查询的代码,通过请求你会发现返回的数据就是包含total,还有其他的数据库数据。
@PostMapping("/queryByPage")
public IPage<TestPlus> queryByPage(TestPlus testPlus, Integer page, Integer limit) {
// 根据邮箱的名字进行动态模糊查询,如果邮箱不为空,就like查询(%%),like可以选择左like,右like,当然你也可以写eq,ge,le等相关的条件。查询的page为传人的 testPlusPage,
// 如果不用mybatis-plus提供的查询,自己只要单独写一个mapper层,同样把创建的testPlusPage对象传人即可(此法不再演示,类似于传统的mybatis)
// 同时包含in的查询,下面的是年龄在这个集合中的数据
Page<TestPlus> testPlusPage = new Page<>(page, limit);
ArrayList<Integer> ages = new ArrayList<>();
ages.add(11);
ages.add(12);
ages.add(31);
ages.add(21);
IPage<TestPlus> testPlusIPages = testPlusService.getBaseMapper().selectPage(testPlusPage, new QueryWrapper<TestPlus>().lambda()
.like(StringUtils.isNotEmpty(testPlus.getEmail()), TestPlus::getEmail, testPlus.getEmail())
.in(TestPlus::getAge,ages));
return testPlusIPages;
}
5.根据id查询单个数据,以上都是基于baseMapper的相关查询,其实mybatis-plus同样也为我们封装了很多service常见的方法。下面就是一个查询单个。
mybatis-plus的条件构造器还是挺灵活的,可以根据文章开头的表达式表格进行拼接。
@PostMapping("/queryById")
public TestPlus delete(String id) {
// 根据id查询单个数据。service有很多的方法可以调用。这里只说一个。
// eq说明的是id与之相等,注意这里的id我传人的是String类型的,但是也可以查询到数据,mybatis-plus会很聪明的自动进行转换。
// last说明的是在末尾拼接sql(可参照文章开头的表达式表格),查询一条数据(id也可以查询一条,笔者只不过为了说明这个写法的意思)
// select的意思是我只查询TestPlus中email和emailPassword所对应的数据库字段,其他的字段内容我不查询
TestPlus one = testPlusService.getOne(new QueryWrapper<TestPlus>().lambda()
.eq(TestPlus::getId, id)
.last("limit 1")
.select(TestPlus::getEmail, TestPlus::getEmailPassword));
return one;
}
结果如下所示
6.数据的批量插入操作
在一些特殊的情况下,我们需要批量插入一定的数据。比如一个集合,里面包含了很多个数据库对应的实体对象。这个时候我们需要对其进行批量入库,笔者目前只发现了,service有批量插入的方法,mapper未发现有类似的方法。
@PostMapping("/saveBatch")
public void saveBatch() {
List<TestPlus> testPluses = new ArrayList<>();
TestPlus testPlus;
for (int i = 0; i < 10; i++) {
testPlus = new TestPlus();
testPlus.setCreateTime(LocalDateTime.now());
testPlus.setAge(10 + i);
testPlus.setEmail("zhangsan" + i);
testPlus.setEmailPassword("zhangsanpassword" + i);
testPlus.setPassword("pss" + i);
testPlus.setUsername("psy" + i);
testPluses.add(testPlus);
}
boolean b = testPlusService.saveBatch(testPluses, testPluses.size());
if (b) {
log.info("批量入库完毕!");
}
}
数据库的结果如下所示
mybatis是一款完全支持mybatis的升级型框架
1:封装了mapper层的代码,service层的代码。同样支持抒写sql语句,使用起来很方便,对于单表就是解放的号角。
2:可以将参数自动的转换成对应的类型,前提是参数是能够转成数字,不能把字符串a转成数字
3:丰富的构造器功能,分为查询构造器,和更新构造器,牛比的baseMapper。
4:service和mapper层的丰富api,完全满足于单表的所有需求。
5:表达式支持动态查询,如下所示的一个动态查询
IPage<CpaBehaviorData> cpaRetainedIPage = iCpaBehaviorService.getBaseMapper().selectPage(cpaRetainedPage, new QueryWrapper<CpaBehaviorData>().lambda()
.like(!StringUtils.isBlank(uploadPath), CpaBehaviorData::getUploadPath, uploadPath)
.eq(CpaBehaviorData::getRetainedStatus, 1)
.eq(!StringUtils.isBlank(isDoSign), CpaBehaviorData::getIsDoSign, isDoSign)
// 大于等于开始的时间
.ge(!StringUtils.isBlank(uploadStartTime), CpaBehaviorData::getUploadTime, uploadStartTime)
// 小于等于结束的时间
.le(!StringUtils.isBlank(uploadEndTime), CpaBehaviorData::getUploadTime, uploadEndTime)
);
以上就是一些简单的crud操作,先查询后更新会更稳。至于复杂的sql,如果mybatis-plus条件构造器实在不会组装,那就是考验我们写sql的能力了,恢复到mybatis的功能,未必有所损失!