MyBatis-Plus总结
一、MyBatis回顾
(1)什么是MyBatis:MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。MyBatis-Plus其实就是对MyBatis的加强。
二、什么是MyBatis-Plus
(1)MyBatis-Plus是MyBatis的增强,在MyBatis的基础上,只做增强而不做改变,是为了简化开发、提高效率而生。
(2)MyBatis-Plus所需要的依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.wolfcode.mp</groupId>
<artifactId>mybatis_plus_demo</artifactId>
<version>1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
</parent>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
(3)创建自定义一个mapper接口(如:EmployeeMapper.java)然后继承BaseMapper,如:
public interface EmployeeMapper extends BaseMapper<Employee> {
}
三、MyBatis-Plus常用注解
(1)@TableName:表名注解。作用:该注解是用于当你所创建的实体类的类名与你的表名不一致时,可使用该注解。如:
如果表名为t_employee,而对应的实体类为Employee,此时就需要使用@TableName注解
@TableName("t_employee")
public class Employee{}
(2)@TableField:字段注解(非主键)。作用:当实体类中的属性名与对应表的列名不一致时,则需要使用该注解,该注解有两种使用方式。如:
使用方式一:
现在有一个表叫employee表,表中有一个ename列,而对应的实体类中的属性名为name,此时就需要使用到@TableField声明。
@TableField("ename")
private String name;
使用方式二:当我们需要在对应表的实体类中声明一个非该表中的列的属性时,如:现在Employee类中声明一个isDelete属性,而该属性在对应的employee表中并没有对应的列,则此时该使用@TableField(exist=false),其中:exist属性表示当前属性是否映射数据库列。
(3)@TableId:主键注解。作用:标记当前属性映射对应表中的主键。如:
@TableId(value = "id", type = IdType.AUTO)
private Long id;
其中:type属性指定主键类型
① IdType.AUTO
数据库ID自增
② IdType.NONE
无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
③ IdType.INPUT
insert前自行set主键值
④ IdType.ASSIGN_ID
分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)
⑤ IdType.ASSIGN_UUID
分配UUID,主键类型为String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认default方法)
四、通用Mapper接口
4.1 inser接口:
/**
* 需求:插入一条记录
* insert接口
* 拼接的sql:INSERT INTO employee ( name, password, email, age, admin, dept_id ) VALUES ( ?, ?, ?, ?, ?, ? )
*/
@Test
public void testSave() {
Employee employee = new Employee();
employee.setAdmin(1);
employee.setAge(18);
employee.setDeptId(1L);
employee.setEmail("dafei@wolfcode.cn");
employee.setName("dafei");
employee.setPassword("1");
employeeMapper.insert(employee);
}
4.2 update接口:
4.2.1 updateById接口
/**
* 需求:更新id为1的name为dafei
* updateById接口
* 拼接的sql:UPDATE employee SET name=?, age=?, admin=? WHERE id=?
*/
@Test
public void testUpdateById() {
Employee employee = new Employee();
employee.setId(1L);
employee.setName("dafei");
employeeMapper.updateById(employee);
}
注意:(1)使用updateById接口方式,当传入的实体对象参数,如果属性类型是基本数据类型,则mybatis-plus会认为有默认值,则会参与sql的拼接。
(2)使用updateById接口方式,当传入的实体对象参数,如果属性类型是包装类类型,则不会参与sql的拼接。
4.2.2 update接口
注意:该接口里需要传一个 entity和 wrapper 集合 这两个参数
/**
*需求:更新id为1的name为zhoujie
* update接口:该接口里需要传一个 entity和 wrapper 集合 这两个参数
* 拼接的sql:UPDATE employee SET name=? WHERE (id = ?)
* wrapper.eq("id", 1L)等价于sql中的:WHERE (id = ?)
* wrapper.set("name", "zhoujie")等价于sql中的:SET name=?
*/
@Test
public void testUpdate() {
UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
wrapper.eq("id", 1L).set("name", "zhoujie");
employeeMapper.update(null, wrapper);
}
(1)其中 wrapper.eq(“id”, 1L)等价于:WHERE (id = 1L), wrapper.set(“name”, “zhoujie”)等价于:SET name=zhoujie
(2)update 与 updateById 的选用:
updateById: 1> 更新条件为id。 2> 全量(所有字段)更新。
update: 1> 更新条件有多个(不仅限于根据id更新)。2> 局部(部分字段)更新。
4.3 delete接口:
4.3.1 deleteById接口
/**
* 需求:根据id删除
* deleteById接口
* 拼接的sql:DELETE FROM employee WHERE id=?
*/
@Test
public void testDeleteById() {
employeeMapper.deleteById(1L);
}
4.3.2 deleteBatchIds接口
(该接口需要传一个集合,可用于批量删除)
/**
* 需求:删除id=1, id=2的员工信息
* deleteBatchIds接口:该接口需要传一个集合,可用于批量删除
* 拼接的sql:DELETE FROM employee WHERE id IN ( ? , ? )
*/
@Test
public void testDeleteBatchIds() {
employeeMapper.deleteBatchIds(Arrays.asList(1L,2L));
}
4.3.3 deleteByMap接口
注意:该接口里面需要传一个map集合,且拼接出的sql语句中的条件只能是使用and进行连接
/**
* 需求:删除name=dafei并且age=18的员工信息
* deleteByMap接口:该接口里面需要传一个map集合
* 拼接的sql:Preparing: DELETE FROM employee WHERE name = ? AND age = ?
*/
@Test
public void testDeleteByMap() {
Map<String, Object> map = new HashMap<>();
map.put("name", "赵一明");
map.put("age", 25);
employeeMapper.deleteByMap(map);
}
4.3.4 delete接口
注意: delete接口:该接口里面需要传一个 wrapper 集合
/**
* 需求:删除name=钱总并且age=31的员工信息 wrapper 集合
* delete接口:该接口里面需要传一个 wrapper 集合
* sql:DELETE FROM employee WHERE (name = ? AND age = ?)
*/
@Test
public void testDelete() {
UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
wrapper.eq("name", "钱总").eq("age", 31);
employeeMapper.delete(wrapper);
}
4.4 select接口:
4.4.1 selectById接口
/**
* 需求:查询id=5的员工信息
* selectById接口
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE id=?
*/
@Test
public void testSelectById() {
System.out.println(employeeMapper.selectById(5L));
}
4.4.2 selectBatchIds接口
**注意:**selectBatchIds接口:该接口里面需要传一个list集合
/**
* 需求:查询id=1,id=2的员工信息
* selectBatchIds接口:该接口里面需要传一个list集合
* 适用场景:当需要查指定哪些id的数据时可使用,其拼接的sql语句使用的是in来实现的。
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE id IN ( ? , ? )
*/
@Test
public void testSelectBatchIds() {
employeeMapper.selectBatchIds(Arrays.asList(5L,6L)).forEach(System.out::println);
}
4.4.3 selectByMap接口
注意:selectByMap接口:里面需要传一个 map 集合,传的map集合,且拼接出的sql语句中的条件只能是使用and进行连接
/**
* 需求: 查询name=钱二明, age=25的员工信息
* selectByMap接口:里面需要传一个 map 集合,传的map集合,需拼接出的sql语句中的条件只能是使用and进行连接
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE name = ? AND age = ?
*/
@Test
public void testSelectByMap() {
Map<String, Object> map = new HashMap<>();
map.put("name", "钱二明");
map.put("age", 25);
employeeMapper.selectByMap(map);
}
4.4.4 selectCount接口
注意:selectCount接口:里面需要传一个 wrapper 集合,若 wrapper 集合中不设置任何条件值,则默认查询全部数量
/**
* 需求: 查询满足条件的所有的员工个数
* selectCount接口:里面需要传一个 wrapper 集合,若 wrapper 集合中不设置任何条件值,则默认查询全部数量
* 拼接的sql: SELECT COUNT( 1 ) FROM employee
*/
@Test
public void testSelectCount() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
employeeMapper.selectCount(wrapper);
}
4.4.5 selectList接口
注意:selectList接口:里面需要传一个 wrapper 集合
/**
* 需求: 查询满足条件的所有的员工信
* selectList接口:里面需要传一个 wrapper 集合
* 返回值: List<Employee>
* 拼接的sql:
* 当 wrapper 集合中没有设置条件时,即查询全部:SELECT id,name,password,email,age,admin,dept_id FROM employee
* 当 wrapper 集合中设置了条件时,即按设置的条件查询:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (age = ?)
*/
@Test
public void testSelectList() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.eq("age", 25);
List<Employee> employees = employeeMapper.selectList(wrapper);
}
4.4.6 selectMaps接口
注意:selectMaps接口:里面需要传一个 wrapper 集合
/**
* 需求: 查询满足条件的所有的员工信息
* selectMaps接口:里面需要传一个 wrapper 集合
* 返回值:List<Map<String, Object>>
* 拼接的sql:
* 当 wrapper 集合中没有设置条件时,即查询全部:SELECT id,name,password,email,age,admin,dept_id FROM employee
* 当 wrapper 集合中设置了条件时,即按设置的条件查询:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (age = ?)
*/
@Test
public void testSelectMaps() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
List<Map<String, Object>> maps = employeeMapper.selectMaps(wrapper);
}
注意:什么时候使用 selectList 接口,什么时候使用 selectMaps 接口?
能封装成对象时,使用 selectList 接口,不能封装成对象时,使用 selectMaps 接口
比如如下要求:
查询每个部门下员工的个数
sql: select dept_id , count(id) count from employee group by dept_id
结果是:dept_id 与 count 列,而表与对应的实体类并没有 count 列/属性,此时,如果使用 selectList 进行查询,则会丢失数据。
4.4.7 selectPage接口
步骤1:在启动类中配置分页拦截器
//分页拦截器
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setOverflow(true); //合理化
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
步骤2:
注意:
(1)分页返回的数据是实体对象(page)
(2)selectPage接口:该接口里面需要传一个 Page 对象,wrapper 集合,其中 wrapper 是过滤条件
(3)Page<>(2,3)中的参数:参数1:当前页。参数2:每页显示条数
/**
* 需求:查询第二页员工数据, 每页显示3条
* 分页返回的数据是实体对象(page)
* selectPage接口:该接口里面需要传一个 Page 对象,wrapper 集合,其中 wrapper 是过滤条件
* Page<>(2,3)中的参数:参数1:当前页。参数2:每页显示条数
* 拼接的sql:
* SELECT COUNT(1) FROM employee
* SELECT id,name,password,email,age,admin,dept_id FROM employee LIMIT ?,?
*/
@Test
public void testSelectPage() {
IPage<Employee> page = new Page<>(2,3);
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
page = employeeMapper.selectPage(page, wrapper);
System.out.println("当前页:" + page.getCurrent());
System.out.println("每页显示条数:" + page.getSize());
System.out.println("总页数:" + page.getPages());
System.out.println("总数:" + page.getTotal());
System.out.println("当前页数据:" + page.getRecords());
}
五、条件构造器
5.1 继承体系
(1)继承体系图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V2rwTKxX-1642229759087)(D:\图片\java\image-20211222115421170.png)]
(2)继承关系说明:
1> Wapper:条件构造抽象类,最顶端父类。
2> AbstractWrapper: 用于查询条件封装,生成 sql 的 where 条件。继承 Wapper 抽象类。
3> QueryWrapper: Entity 对象封装操作类,不是用lambda语法。适用于查询。
4> UpdateWrapper: Update 条件封装,适用于Entity对象更新操作。
5> AbstractLambdaWrapper: Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。
6> LambdaQueryWrapper:看名称也能明白就是用于Lambda语法使用的查询Wrapper。
7> LambdaUpdateWrapper: Lambda 更新封装Wrapper。
5.1.1 共有条件方法(经常使用的)
(1)allEq方法
/**
* allEq方法
* 拼接的sql:
* wrapper.allEq(Map<String, Object> prams):
* SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name = ? AND age = ?)
* wrapper.allEq(Map<String, Object> prams, boolean null2IsNull):
* 该方法的第二参数表示:
* 当你拼接的条件中有null,并且第二个参数设置为true时,则在拼接sql语句时,会把条件拼接上去,如:
* SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name = ? AND age IS NULL)
* 当你拼接的条件中有null,并且第二个参数设置为false时,则在拼接sql语句时,不会把条件拼接上去,如:
* SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name = ?)
*/
@Test
public void testAllEq() {
Employee employee = new Employee();
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
Map<String, Object> map = new HashMap<>();
map.put("name", "xiaofei");
map.put("age", null);
wrapper.allEq(map);
// wrapper.allEq(map, false);
System.out.println(employeeMapper.selectOne(wrapper));
}
(2)eq方法
/**
* eq方法:等价于 sql 语句中的 where 列名 = ?
* 拼接的sql:
* SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name = ? AND age = ?)
* 加了wrapper.or();语句:
* SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name = ? OR age = ?)
*/
@Test
public void testEq() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.eq("name", "xiaofei");
// wrapper.or();
wrapper.eq("age", 18);
employeeMapper.selectOne(wrapper);
}
(3)ne方法
/**
* ne方法:等价于sql语句中的 where 列名 != ? (WHERE (name <> ?))
* 拼接的sql:
* SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name <> ?)
*/
@Test
public void testNe() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.ne("name", "xiaofei");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
(4)like方法
/**
* like方法:等价于 sql 语句中的 where 列名 like ?
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name LIKE ?)
* 条件中的 ? 参数:%值%
*
*/
@Test
public void testLike() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.like("name", "李");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
5.2 更新操作
5.2.1 UpdateWrapper更新之setSql
/**
* 需求:将id=20的用户name改为dafei
* 拼接的sql:UPDATE employee SET name='dafei' WHERE (id = ?)
*/
@Test
public void testSetSql() {
UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
wrapper.eq("id", 20);
wrapper.setSql("name='dafei'");
employeeMapper.update(null , wrapper);
}
5.2.2 LambdaUpdateWrapper更新
/**
* LambdaUpdateWrapper更新
* 需求:将id=1的用户name改为xiaofei
* 拼接的sql:UPDATE employee SET name=? WHERE (id = ?)
*/
@Test
public void testLambdaUpdateWrapperUpdate() {
LambdaUpdateWrapper<Employee> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(Employee::getId, 20L);
wrapper.set(Employee::getName,"xiaofei");
employeeMapper.update(null , wrapper);
}
5.3 查询操作
5.3.1 QueryWrapper查询
/**
* QueryWrapper查询
* 需求:查询name=dafei, age=18的用户
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name = ? AND age = ?)
*/
@Test
public void testQueryWrapperSelect() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.eq("name", "dafei").eq("age", 18);
employeeMapper.selectList(wrapper);
}
5.3.2 LambdaQueryWrapper查询
/**
* LambdaQueryWrapper查询
* 需求:查询name=dafei, age=18的用户
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name = ? AND age = ?)
*/
@Test
public void testLambdaQueryWrapperSelect() {
LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Employee::getName,"dafei");
wrapper.eq(Employee::getAge,18);
employeeMapper.selectList(wrapper);
}
六、高级查询
6.1 列投影(select)
/**
* 需求:查询所有员工, 返回员工name, age列
* 拼接的sql:SELECT name,age FROM employee
* wrapper.select("name","age");等价于sql语句中的:SELECT name,age
*/
@Test
public void testSelect() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.select("name","age");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
6.2 排序
6.2.1 orderByAsc/orderByDesc排序
/**
* 需求:查询所有员工信息按age正序排, 如果age一样, 按id正序排
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee ORDER BY age ASC,id ASC
* wrapper.orderByAsc("age","id");等价于sql语句中的:ORDER BY age ASC,id ASC
*/
@Test
public void testSort() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.orderByAsc("age","id");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
6.2.2 orderBy排序
/**
* 需求:查询所有员工信息按age正序排, 如果age一样, 按id正序排
* 参数说明:参数一:是否进行排序、参数二:是否进行正序排序、参数三:排序的列名
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee ORDER BY age ASC,id ASC
*/
@Test
public void testOrderBy() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.orderBy(true, true, "age","id");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
6.3 分组查询
6.3.1 groupBy
/**
* 需求: 以部门id进行分组查询,查每个部门员工个数
* 拼接的sql:SELECT dept_id,count(id) FROM employee GROUP BY dept_id
* wrapper.groupBy("dept_id");等价于sql中的:GROUP BY dept_id
*/
@Test
public void testGroupBy() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.groupBy("dept_id");
wrapper.select("dept_id","count(id)");
employeeMapper.selectMaps(wrapper).forEach(System.out::println);
}
6.3.2 having
/**
* 需求: 以部门id进行分组查询,查每个部门员工个数, 将大于3人的部门过滤出来
* 拼接的sql:SELECT dept_id,count(id) count FROM employee GROUP BY dept_id HAVING count > 3
* wrapper.having("count > 3");等价于sql中的:HAVING count > 3
*/
@Test
public void testHaving() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.groupBy("dept_id");
wrapper.select("dept_id","count(id) count");
wrapper.having("count > 3");
employeeMapper.selectMaps(wrapper).forEach(System.out::println);
}
6.4 条件查询
6.4.1 比较运算符
(1)大于(gt)、小于(lt)、大于等于(ge)、小于等于(le)
/**
* 大于:gt
* 需求:查询age 大于18岁员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (age > ?)
* wrapper.gt("age", 18);等价于sql中的:WHERE (age > ?)
*/
@Test
public void testGt() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18);
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
/**
* 小于:lt
* 需求:查询age 小于30岁员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (age < ?)
* wrapper.lt("age", 30);等价于sql中的WHERE (age < ?)
*/
@Test
public void testLt() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.lt("age", 30);
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
/**
* 大于等于:ge
* 需求:查询age 大于等于20岁员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (age >= ?)
* wrapper.ge("age", 20);等价于sql中的WHERE (age >= ?)
*/
@Test
public void testGe() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.ge("age", 20);
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
/**
* 小于等于:le
* 需求:查询age 小于等于20岁员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (age <= ?)
* wrapper.le("age", 20);等价于sql中的:WHERE (age <= ?)
*/
@Test
public void testLe() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.le("age", 20);
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
(2)between/notBetween
/**
* 需求:查询年龄介于18~30岁的员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (age BETWEEN ? AND ?)
* wrapper.between("age", 18, 30);等价于sql中的:WHERE (age BETWEEN ? AND ?)
*/
@Test
public void testBetweenAnd() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.between("age", 18, 30);
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
/**
* 需求:查询年龄小于18或者大于30岁的员工信息【用between实现】
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (age NOT BETWEEN ? AND ?)
* wrapper.notBetween("age", 18, 30);等价于sql中的WHERE (age NOT BETWEEN ? AND ?)
*/
@Test
public void testNotBetweenAnd() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.notBetween("age", 18, 30);
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
(3)isNull/isNotNull
/**
* 需求: 查询dept_id 为null 员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (dept_id IS NULL)
* wrapper.isNull("dept_id");等价于sql中的WHERE (dept_id IS NULL)
*/
@Test
public void testIsNull() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.isNull("dept_id");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
/**
* 需求: 查询dept_id 不为null 员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (dept_id IS NOT NULL)
* wrapper.isNotNull("dept_id");等价于sql中的:WHERE (dept_id IS NOT NULL)
*/
@Test
public void testIsNotNull() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.isNotNull("dept_id");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
(4)in/notIn/inSql/notInSql
/**
* in方法
* 需求: 查询id为1, 2 的员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (id IN (?,?))
* wrapper.in("id", 1,2);等价于sql中的:WHERE (id IN (?,?))
*/
@Test
public void testIn() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.in("id", 1,2);
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
/**
* notIn方法
* 需求: 查询id不为1, 2 的员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (id NOT IN (?,?))
* wrapper.notIn("id", 1,2);等价于sql中的:WHERE (id NOT IN (?,?))
*/
@Test
public void testNotIn() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.notIn("id", 1,2);
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
/**
* inSql方法
* 需求: 查询id为1, 2 的员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (id IN (1,2))
* wrapper.inSql("id", 1,2);等价于sql中的:WHERE (id IN (1,2))
*/
@Test
public void testinSql() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.inSql("id", "1,2");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
/**
* notInSql方法
* 需求: 查询id为1, 2 的员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (id NOT IN (1,2))
* wrapper.notInSql("id", 1,2);等价于sql中的:WHERE (id NOT IN (1,2))
*/
@Test
public void testNotInSql() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.notInSql("id", "1,2");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
}
6.4.2 模糊查询
(1)like/notLike
@Test
public void testLike() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.like("name", "李");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
/**
* 需求: 查询name中不含有fei字样的员工
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name NOT LIKE ?)
* 拼接的参数:%fei%
* wrapper.notLike("name", "fei");等价于sql中的:WHERE (name NOT LIKE ?)
*/
@Test
public void testNotLike() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.notLike("name", "fei");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
(2)likeLeft/likeRight
/**
* 需求: 查询name以fei结尾的员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name LIKE ?)
* 拼接的参数:%fei
* wrapper.likeRight("name", "fei");等价于sql中的:WHERE (name LIKE ?)
*/
@Test
public void testLkeLeft() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.likeLeft("name", "fei");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
/**
* 需求: 查询name以fei开头的员工信息
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name LIKE ?)
* 拼接的参数:fei%
* wrapper.likeRight("name", "fei");等价于sql中的:WHERE (name LIKE ?)
*/
@Test
public void testLkeRight() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.likeRight("name", "fei");
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
6.4.3 逻辑运算符
(1)嵌套or
/**
* 需求:查询name含有fei字样的,或者 年龄在18到30之间的用户
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name LIKE ? OR (age >= ? AND age <= ?))
* rapper.like("name", "fei").or(wp -> wp.ge("age", 18).le("age", 30));等价于sql中的:WHERE (name LIKE ? OR (age >= ? AND age <= ?))
*/
@Test
public void testOr() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.like("name", "fei")
.or(
wp -> wp.ge("age", 18).le("age", 30)
);
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
(2)嵌套and
/**
* 需求:查询name含有fei字样的并且 年龄在小于18或者大于30的用户
* 拼接的sql:SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name LIKE ? AND (age <= ? OR age >= ?))
* wrapper.like("name", "fei").and(wp -> wp.le("age", 18).or().ge("age", 30));等价于sql中的:WHERE (name LIKE ? AND (age <= ? OR age >= ?))
*/
@Test
public void testAnd() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.like("name", "fei")
.and(
wp -> wp.le("age", 18)
.or()
.ge("age", 30)
);
employeeMapper.selectList(wrapper).forEach(System.out::println);
}
七、通用Service接口
7.1 通用方式
步骤一:自定义一个 Service 接口,然后继承 IService。其中里面的泛型应给实体类。
public interface IEmployeeService extends IService<Employee> {
}
步骤二:自定义一个 Service 接口的实现类 ServiceImpl ,然后继承 ServiceImpl<M,T> 的同时实现 Service 接口。
其中 ServiceImpl<M,T> 中的泛型解释:泛型一:对应的 Mapper 接口。泛型二:对应的实体类
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {
}
7.2 常用方法
7.2.1 getBaseMapper()方法
@Test
public void testGetBaseMapper() {
BaseMapper<Employee> baseMapper = employeeService.getBaseMapper();
System.out.println(baseMapper);
}
7.2.2 getOne(wrapper)方法
/**
* getOne方法
* 指定条件查询单个, 结果数据超过1个报错
*/
@Test
public void testGetOne() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.eq("name", "xiaofei");
System.out.println(employeeService.getOne(wrapper));
}
7.2.3 list(wrapper)方法
/**
* list方法
* 指定条件查询多个
*/
@Test
public void testList() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.eq("age", 25);
employeeService.list(wrapper).forEach(System.out::println);
}
7.2.4 page(page, wrapper)
Service接口:
public interface IEmployeeService extends IService<Employee> {
Page<Employee> queryPage(EmployeeQuery qo);
}
ServiceImpl实现类:
@Service
@Transactional
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {
@Override
public Page<Employee> queryPage(EmployeeQuery qo) {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
Page<Employee> page = new Page<>(qo.getCurrentPage(), qo.getPageSize());
wrapper.like(StringUtils.hasLength(qo.getKeyWord()), "name", qo.getKeyWord());
return super.page(page, wrapper);
}
}
测试类:
/**
* 分页+高级查询
* 拼接的sql: SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name LIKE ?) LIMIT ?
*/
@Test
public void testPage() {
EmployeeQuery qo = new EmployeeQuery();
// qo.setKeyWord("孙");
qo.setCurrentPage(1);
qo.setPageSize(3);
Page<Employee> page = employeeService.queryPage(qo);
System.out.println("当前页:" + page.getCurrent());
System.out.println("总页数:" + page.getPages());
System.out.println("每页显示条数:" + page.getSize());
System.out.println("当前页显示记录:" + page.getRecords());
}
7.2.5 saveOrUpdate方法
/**
* saveOrUpdate方法
* 拼接的sql:INSERT INTO employee ( name, age ) VALUES ( ?, ? )
*/
@Test
public void testSaveOrUpdate() {
Employee employee = new Employee();
employee.setName("xiaojie");
employee.setAge(21);
employeeService.saveOrUpdate(employee);
}