目录
3、通用CRUD
3.1 插入操作
3.1.1 方法定义
3.1.2 测试用例
3.1.3 测试
3.1.4 @TableField
3.2 更新操作
3.2.1 根据id更新
3.2.2 根据条件更新
3.3 删除操作
3.3.1 根据id删除(deleteById)
3.3.2 根据Map删除数据(deleteByMap)
3.3.3 根据Wrapper删除数据 (delete)
3.3.4 根据id集合批量删除 (deleteBatchIds)
3.4 查询操作
3.4.1 根据ID查询 (selectById)
3.4.2 根据ID 批量查询(selectBatchIds)
3.4.3 根据 entity 条件,查询一条记录 (selectOne)
3.4.4 根据wrapper条件,查询总记录数(selectCount)
3.4.5 根据 entity 条件,查询全部记录(selectList)
3.4.6 根据 entity 条件,查询全部记录并翻页(selectPage)
3.5 SQL注入的原理
3、通用CRUD
通过前面的学习,我们了解到通过继承BaseMapper就可以获取到各种各样的单表操作,接下来我们将详细讲解这些操作
3.1 插入操作
3.1.1 方法定义
3.1.2 测试用例
@RunWith 就是一个运行器 |
@RunWith(JUnit4.class) 就是指用JUnit4来运行 |
@RunWith(SpringJUnit4ClassRunner.class),让测试运行于Spring测试环境 |
@ContextConfiguration Spring整合JUnit4测试时,使用注解引入多个配置文件 单个文件 @ContextConfiguration(Locations=“classpath:applicationContext.xml”) @ContextConfiguration(classes = SimpleConfiguration.class) 多个文件时,可用{} @ContextConfiguration(locations = { “classpath:spring1.xml”, “classpath:spring2.xml” }) 在SpringBoot2.2.0以前是JUnit4,在SpringBoot之后是JUnit5,对于Junit4而言,所有的测试方法应当是public声明的,而Junit5不用 |
3.1.3 测试
id生成策略不对:
如何设置id的生成策略呢?
MP支持的id策略: |
我们要修改User对象,指定id类型为自增长:
再次测试,数据插入成功:
3.1.4 @TableField
在MP中通过@TableField注解可以指定字段的一些属性,常常解决的问题有2个: 1、对象中的属性名和字段名不一致的问题(非驼峰) 2、对象中的属性字段在表中不存在的问题 |
使用: 其他用法,如大字段不加入查询字段:(即,查询时不返回该字段的值) 效果: |
3.2 更新操作
在MP中,更新操作有2种,一种是根据id更新,另一种是根据条件更新
3.2.1 根据id更新
方法定义: 测试用例: 测试结果: 数据库结果: |
3.2.2 根据条件更新
方法定义: 测试用例:(QueryWrapper没有set方法,只能通过创建对象,通过对象来调用set方式,从而实现属性值的更新;而UpdateWarpper可以直接使用set方法指定数据库表字段名进行对应的修改)
或者,通过UpdateWrapper进行更新: 测试结果: 关于wrapper更多的用法后面会有详细讲解 |
3.3 删除操作
3.3.1 根据id删除(deleteById)
方法定义: 测试用例:(这里指定id为 6L 的原因是因为id的类型为 long) 结果: 数据被删除: |
3.3.2 根据Map删除数据(deleteByMap)
方法定义: 测试用例:(Map中的元素相当于where语句,多条件之间是 and 关系) 结果: |
3.3.3 根据Wrapper删除数据 (delete)
方法定义: 测试用例:(根据包装的参数进行删除) wrapper有两种写法: 推荐使用第二种用法,因为该用法不用手写字段名,减少了错误可能发生的概率 结果: |
3.3.4 根据id集合批量删除 (deleteBatchIds)
方法定义: 测试用例: 结果: |
3.4 查询操作
MP提供了多种查询操作,包括根据id查询、批量查询、查询单条数据、查询列表、分页查询等操作
3.4.1 根据ID查询 (selectById)
方法定义: 测试用例:(如果查询的数据不存在,则会返回null) 结果: |
3.4.2 根据ID 批量查询(selectBatchIds)
方法定义: 测试用例:(集合中的元素即为查询条件) 结果: |
3.4.3 根据 entity 条件,查询一条记录 (selectOne)
方法定义: 测试用例: 结果: 如果要查询的数据超过一条时,会抛出异常: |
3.4.4 根据wrapper条件,查询总记录数(selectCount)
方法定义: 测试用例:(eq:等于,gt:大于) 结果:
|
3.4.5 根据 entity 条件,查询全部记录(selectList)
方法定义:
测试用例:(like:以%val值%的形式进行模糊查找)
结果: |
3.4.6 根据 entity 条件,查询全部记录并翻页(selectPage)
方法定义:(首先要配置MP底层提供的一个分页插件PaginationInterceptor) 配置分页插件:(【Java Web】014 -- SpringBoot原理(配置优先级、Bean管理、SpringBoot原理 中的bean管理内容,通过声明配置类来管理第三方bean对象) 测试用例:(查询用户表中年龄大于20岁的用户) 结果: |
3.5 SQL注入的原理
前面我们已经知道,MP在启动后会将BaseMapper中的一系列的方法注册到mappedStatements那么究竟是如何注入的呢?流程又是怎么样的?下面我们将一起来分析下。
在MP中,ISqlInjector负责SQL的注入工作,它是一个接口,AbstractSqlInjector是它的实现类,实现关系如下:
在AbstractSqlInjector中,主要是由inspectInject()方法进行注入的,如下:
在实现方法中, methodList.forEach(m -> m.inject(builderAssistant, mapperClass,modelClass,tableInfo)); 是关键,循环遍历方法,进行注入。
最终调用抽象方法injectMappedStatement进行真正的注入:
查看该方法的实现:
以SelectById为例查看:
可以看到,生成了SqlSource对象,再将SQL通过addSelectMappedStatement方法添加到mappedStatements中