MyBatis-Plus
以下内容若有误,欢迎私信我或在下方留言,谢谢^_−
一、简介
MyBatis-Plus简称MP,对原来的 MyBatis 进行了增强,目的是为了简化开发、提高效率。其具有多种特性,比如
低侵入:引入MyBatis-Plus后并不会对现有的项目产生影响,这也是MyBatis-Plus的愿景,只做增强,不做改变。
损耗小:当我们引入依赖的时候,我们会发现该依赖的id带有starter,说明这是一个支持自动装配的工具,所以,在项目启动时就会自动注入基本的CRUD,对于性能来说基本没有任何损耗。
分页插件支持多种数据库:比如MySQL、Oracle、DB2、SQLServer等
支持主键自动生成:MyBatis-Plus支持多种主键策略,包含生成分布式系统中唯一ID
支持Lambda 形式调用、内置分页插件、强大的CRUD操作等。
MyBatis | MP | |
---|---|---|
优点 | ①SQL语句自由控制,较为灵活 ②SQL与业务层分离,易于阅读 ③提供动态SQL语句,控制灵活 | ①提供无代码的CRUD操作 ②内置代码生成器,比如分页插件、性能分析插件等 ③提供了功能丰富的条件构造器 |
缺点 | ①简单的CRUD也需要提供对应SQL语句 ②需要维护大量的xml文件 ③自身功能有限,要拓展需要依赖第三方插件 | ①增强了学习成本 ②mybatis-plus引入第三方插件,未来升级可能会存在兼容性问题 |
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
二、常用注解
注解 | 说明 |
---|---|
@TableName() | 表名注解,指定当前实体类对应数据库中的哪张表,默认与实体类名一致 |
@TableField() | 字段注解(非主键),指定当前属性与表中哪一列映射,默认与属性名一致 |
@TableId() | 主键注解,标记当前属性映射表中主键(实体类中id没有明确指定id生成规则时,默认使用雪花算法) |
@Version() | 用于标记乐观锁操作字段 |
@TableName("t_employee")
public class Employee_bak {
@TableId(value = "id", type = IdType.AUTO) // type 主键类型
private Long id;
@TableField(value = "ename") // value 表中列名
private String name;
private String password;
private String email;
private int age;
private int admin;
private Long deptId;
@TableField(exist = false) // exist 是否为数据库表字段
private Department dept;
}
参数丢失:由于一些不当的操作,将数据库中的某些数据丢失了
mybatis-plus sql拼接规则:
①实体对象属性有值,则属性名会拼接到SQL中
②实体对象属性类型为基本类型,会有默认值,mybatis-plus认为有值,参与SQL拼接
解决方案:
①将基本数据类型改为包装类型
②执行查询,再替换,后更新
③部分字段更新update(null, wrapper)
/ 自定义update sql
三、通用Mapper接口
日志
第一种:logging.level.cn.regex.mp.mapper=debug
第二种:mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
1.insert
// int insert(T entity);
// INSERT INTO employee ( name, password, email, age, admin, dept_id ) VALUES ( ?, ?, ?, ?, ?, ? )
@Test
public void testInsert(){
Employee employee = new Employee();
employee.setAdmin(1);
employee.setAge(18);
employee.setDeptId(1L);
employee.setEmail("regex@qq.com");
employee.setName("regex");
employee.setPassword("123");
employeeMapper.insert(employee);
}
2.delete
-
deleteById:单个删除,根据指定 ID 删除一条记录
// int deleteById(Serializable id); // DELETE FROM employee WHERE id=? @Test public void testDeleteById() { employeeMapper.deleteById(1L); }
-
deleteBatchIds:批量删除,根据给定的 ID 集合删除多条记录
// int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); // DELETE FROM employee WHERE id IN ( ? , ? ) @Test public void testDeleteBatchIds() { employeeMapper.deleteBatchIds(Arrays.asList(1L, 2L)); }
-
delete:条件删除,根据 entity 条件删除记录
// int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper); // DELETE FROM employee WHERE (name = ? AND age = ?) @Test public void testDelete() { QueryWrapper<Employee> wrapper = new QueryWrapper<>(); wrapper.eq("name", "一明"); wrapper.eq("age", 25); employeeMapper.delete(wrapper); }
-
deleteByMap:条件删除,根据 columnMap 条件删除记录
// int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); // 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); }
3.update
-
updateById:根据 ID 修改
// int updateById(@Param(Constants.ENTITY) T entity); // 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); // 拼接不为null的属性到SQL中 }
▲该方法会将不为null的属性拼接到SQL中,若实体类中包含基本数据类型,则可能导致数据丢失
-
update:根据 whereEntity 条件更新记录
// int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper); // UPDATE employee SET name=? WHERE (id = ?) @Test public void testUpdate() { UpdateWrapper<Employee> wrapper = new UpdateWrapper<>(); wrapper.eq("id", 1L); wrapper.set("name", "regex"); employeeMapper.update(null, wrapper); }
updateById和update选用问题:
如果更新条件是id,并且是全量更新,则使用updateById
如果更新条件不仅限于id,并且部分列更新,则使用update
4.select
-
selectList:根据 entity 条件,查询全部记录
// List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // SELECT id,name,password,email,age,admin,dept_id FROM employee @Test public void testSelectList() { Wrapper<Employee> wrapper = new QueryWrapper<>(); employeeMapper.selectList(wrapper); }
-
selectById:根据 ID 查询
// T selectById(Serializable id); // SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE id=? @Test public void testSelectById() { employeeMapper.selectById(5L); }
-
selectBatchIds:根据 ID 批量查询
// List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); // SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE id IN ( ? , ? , ? ) @Test public void testSelectBatchIds() { employeeMapper.selectBatchIds(Arrays.asList(2L, 3L, 4L)); }
-
selectCount:根据 Wrapper 条件,查询总记录数
// Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // SELECT COUNT( 1 ) FROM employee @Test public void testSelectCount() { employeeMapper.selectCount(null); }
-
selectByMap:根据 columnMap 条件查询
// List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); // SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE name = ? AND admin = ? AND age = ? @Test public void testSelectByMap() { Map<String, Object> map = new HashMap<>(); map.put("name", "孙总"); map.put("age", 35); map.put("admin", 0); employeeMapper.selectByMap(map); }
-
selectMaps:根据 Wrapper 条件查询全部记录,每条记录以键值对形式封装到map中
// List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // SELECT id,name,password,email,age,admin,dept_id FROM employee @Test public void testSelectMaps() { Wrapper<Employee> wrapper = new QueryWrapper<>(); List<Map<String, Object>> maps = employeeMapper.selectMaps(wrapper); maps.forEach(System.err::println); }
-
selectPage:分页查询
注意:需要在启动类中配置分页拦截器
// 分页拦截器 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); paginationInnerInterceptor.setOverflow(true); //合理化 interceptor.addInnerInterceptor(paginationInnerInterceptor); return interceptor; }
// <E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // SELECT id,name,password,email,age,admin,dept_id FROM employee LIMIT ? @Test public void testSelectPage() { Page<Employee> page = new Page<>(1, 5); // 默认第一页,每页10条 Wrapper<Employee> wrapper = new QueryWrapper<>(); Page<Employee> employeePage = employeeMapper.selectPage(page, wrapper); System.out.println("当前页:" + employeePage.getCurrent()); System.out.println("页条数:" + employeePage.getSize()); System.out.println("总条数:" + employeePage.getTotal()); System.out.println("总页数:" + employeePage.getPages()); System.out.println("数据集:" + employeePage.getRecords()); }
selectList和selectMaps选用问题:
当所查询的的数据无法封装成对象时,使用selectMaps
四、条件构造器
条件构造器即根据条件拼接sql的where条件,可以理解为mybatis中的动态SQL或SQL片段
1.继承体系
-
Wrapper:条件构造抽象类,最顶端父类
-
AbstractWrapper: 用于查询条件封装,生成 sql 的 where 条件
-
AbstractLambdaWrapper: Lambda 语法使用 Wrapper 统一处理解析 lambda 获取 column
-
LambdaQueryWrapper:用于 Lambda 语法封装查询条件
-
LambdaUpdateWrapper: 用于 Lambda 语法封装更新条件
-
-
-
QueryWrapper: 封装查询条件
-
UpdateWrapper: 条件封装,用于Entity对象更新操作
-
2.更新操作
eq():用于拼接where条件
set():用于拼接set后面所需要修改的字段和值
// 需求:将id=1的员工age改为18, 如果传入uname变量值不等于null或者“”,修改为员工name为uname变量值
// UPDATE employee SET age=?,name=? WHERE (id = ?)
@Test
public void testUpdate2() {
UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
wrapper.eq("id", 1);
wrapper.set("age", 18);
String uname = "regex+";
if (StringUtils.hasText(uname)) {
wrapper.set("name", uname);
}
employeeMapper.update(null, wrapper);
}
setSql():用于拼接set后面所需要SQL片段
// 需求:将id=1的用户name改为regex
// UPDATE employee SET age=20,name='regex' WHERE (id = ?)
@Test
public void testUpdate3() {
UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
wrapper.eq("id", 1L);
wrapper.setSql("age=20");
String name = "regex";
wrapper.setSql(StringUtils.hasText(name), "name='regex'"); // 里面的regex需要加上单引号
employeeMapper.update(null, wrapper);
}
Lambda 方式更新封装(推荐)
// 需求:将id=1的用户name改为regex
// UPDATE employee SET name=? WHERE (id = ?)
@Test
public void testUpdate4() {
LambdaUpdateWrapper<Employee> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(Employee::getId, 1L);
wrapper.set(Employee::getName, "regex");
employeeMapper.update(null, wrapper);
}
3.查询操作
Lambda 语法使用 Wrapper + 链式编程
// 需求:查询name=regex, age=18的用户
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name = ? AND age = ?)
@Test
public void testSelect2() {
LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Employee::getName, "regex").eq(Employee::getAge, 40);
employeeMapper.selectList(wrapper);
}
4.工具类Wappers
-
new方式
QueryWrapper<Employee> wrapper1 = new QueryWrapper<>(); LambdaQueryWrapper<Employee> wrapper2 = new LambdaQueryWrapper<>();
-
工具类创建
QueryWrapper<Employee> wrapper3 = Wrappers.<Employee>query(); LambdaQueryWrapper<Employee> wrapper4 = Wrappers.<Employee>lambdaQuery();
-
QueryWrapper --> LambdaQueryWrapper
LambdaQueryWrapper<Employee> wrapper5 = wrapper1.lambda();
五、高级查询
1.列投影
select(String… columns):选择需要查询的列
// 需求:查询所有员工, 返回员工name, age列
// SELECT name, age FROM employee
@Test
public void testQuery1() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.select("name", "age");
// wrapper.select("name, age"); // SQL片段
employeeMapper.selectList(wrapper);
}
// 需求:查询所有员工, 返回以a字母开头的列
// SELECT id,age,admin FROM employee
@Test
public void testQuery2() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.select(Employee.class, TableFieldInfo -> TableFieldInfo.getProperty().startsWith("a")); // 过滤查询字段不含主键
employeeMapper.selectList(wrapper);
}
2.排序
// 需求:查询所有员工信息按age正序排, 如果age一样, 按id降序排
@Test
public void testOrder() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
// wrapper.orderByAsc("age").orderByDesc("id");
wrapper.orderBy(true, true, "name");
employeeMapper.selectList(wrapper);
}
3.分组查询
// 需求: 以部门id进行分组查询,查每个部门员工个数, 将大于3人的部门过滤出来
// SELECT count(*) FROM employee GROUP BY dept_id
@Test
public void testGroup() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.groupBy("dept_id")
.select("dept_id", "count(*) '人数'")
// 只能够使用{0}进行占位
.having("count(*) > {0}", 3);
//.having("count(*) > 3");
employeeMapper.selectList(wrapper);
}
4.条件查询
比较运算符 | 含义 |
---|---|
allEq/eq/ne | 全等于/等于/不等于 |
gt/ge/lt/le | 大于/大于等于/小于/小于等于 |
between/notBetween | 在…之间/不在…之间 |
isNull/isNotNull | 为空/不为空 |
in/notIn | 包含/不包含(字段方式) |
inSql/notInSql | 包含/不包含(SQL片段方式) |
// 查询name=regex, age=18的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name = ? AND age = ?)
@Test
public void testAllEq() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
Map<String, Object> map = new HashMap<>();
map.put("name", "regex");
map.put("age", "40");
wrapper.allEq(map);
employeeMapper.selectList(wrapper);
}
// 需求:查询满足条件员工信息, 注意传入的map条件中, 包含a的列才参与条件查询
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name = ?)
@Test
public void testAllEq2() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
Map<String, Object> map = new HashMap<>();
map.put("name", "regex");
map.put("age", "40");
wrapper.allEq((k, v) -> k.contains("m"), map);
employeeMapper.selectList(wrapper);
}
// 需求:查询name=regex员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name = ?)
@Test
public void testEq() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.eq("name", "regex");
employeeMapper.selectList(wrapper);
}
// 需求:查询name !=dafei员工信息
// 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", "regex");
employeeMapper.selectList(wrapper);
}
// 需求:查询age 大于18岁员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (age > ?)
@Test
public void testGt() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18);
employeeMapper.selectList(wrapper);
}
// 需求:查询年龄介于18~30岁的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (age BETWEEN ? AND ?)
@Test
public void testBetween() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.between("age", 18, 30);
employeeMapper.selectList(wrapper);
}
// 需求:查询年龄小于18或者大于30岁的员工信息【用between实现】
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (age NOT BETWEEN ? AND ?)
@Test
public void testNotBetween() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.notBetween("age", 18, 30);
employeeMapper.selectList(wrapper);
}
@Test
public void testNull() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
// 需求: 查询dept_id 为null 员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (dept_id IS NULL)
// wrapper.isNull("dept_id");
// 需求: 查询dept_id 为不为null 员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (dept_id IS NOT NULL)
wrapper.isNotNull("dept_id");
employeeMapper.selectList(wrapper);
}
// 需求: 查询id为1, 2 的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (id IN (?,?))
@Test
public void testIn() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.in("id", 1, 2);
employeeMapper.selectList(wrapper);
}
// 需求: 查询id不为1, 2 的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (id NOT IN (?,?))
@Test
public void testNotIn() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.notIn("id", 1, 2);
employeeMapper.selectList(wrapper);
}
// 需求: 查询id为1, 2 的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (id IN (1,2))
@Test
public void testInSql() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.inSql("id", "1,2");
employeeMapper.selectList(wrapper);
}
// 需求: 查询id不为1, 2 的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (id NOT IN (1, 2))
@Test
public void test() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.notInSql("id", "1, 2");
employeeMapper.selectList(wrapper);
}
模糊查询
like、notLike:匹配值是否包含指定字符串,会自动拼接百分号
likeLeft:%拼在左边
likeRight:%拼在右边
// 需求: 查询name中含有re字样的员工
// 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", "re"); // %re%,会自动拼接百分号
// wrapper.likeLeft("name", "re"); // %re,left指百分号拼接在左边
wrapper.likeRight("name", "re"); // re%,right指百分号拼接在右边
employeeMapper.selectList(wrapper);
}
// 需求: 查询name中不含有fei字样的员工
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name NOT LIKE ?)
@Test
public void testNotLike() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.notLike("name", "re");
employeeMapper.selectList(wrapper);
}
逻辑运算符
or
and:链式操作默认用and拼接
▲注意优先级问题
// 需求: 查询age = 18 或者 name=regex 或者 id =1 的用户
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (age = ? OR name = ? OR id = ?)
@Test
public void testOr() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.eq("age", 18).or().eq("name", "regex").or().eq("id", 1);
employeeMapper.selectList(wrapper);
}
// 需求:查询name含有re字样的,或者 年龄在18到30之间的用户
@Test
public void testOr2() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name LIKE ? OR age >= ? AND age <= ?)
// wrapper.like("name", "re").or().ge("age", 18).le("age", 30);
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name LIKE ? OR (age >= ? AND age <= ?))
wrapper.like("name", "re").or(wr -> wr.ge("age", 18).le("age", 30));
employeeMapper.selectList(wrapper);
}
// 需求:查询name含有re字样的并且 年龄在小于18或者大于30的用户
// SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name LIKE ? AND (age < ? OR age > ?))
@Test
public void testAnd() {
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
// wrapper.like("name", "re").lt("age", 18).or().gt("age", 30); // 错误写法
wrapper.like("name", "re").and(wr -> wr.lt("age", 18).or().gt("age", 30));
employeeMapper.selectList(wrapper);
}
5.自定义SQL
-
mapper.xml方式:与之前没什么区别
-
注解方式
@Select("select * from employee") List<Employee> listByXmlSingle(); @Select("select e.id, e.name, e.password, e.email, e.age, e.admin, d.id d_id, d.name d_name, d.sn d_sn " + "from employee e left join department d " + "on e.dept_id = d.id") @Results({ @Result(column="d_id", property = "dept.id"), @Result(column="d_name", property = "dept.name"), @Result(column="d_sn", property = "dept.sn") }) List<Employee> listByXmlJoin();
六、通用Service接口
1.传统方式
定义Service接口,实现该接口以及其中的五个抽象方法,在实现类中注入mapper,通过mapper对象调用持久层的CRUD方法。由于在项目中很多地方都需要用到这些CRUD方法,如果采用这种方式的话,会造成很多的代码重复。
2.通用方式
-
自定义mapper接口,继承
BaseMapper<T>
-
自定义Service接口,并继承
IService<T>
接口public interface IEmployeeService extends IService<Employee> {}
-
实现Service接口,并继承
ServiceImpl<M, T>
ServiceImpl<M, T>
泛型1:实体类的mapper接口
泛型2:实体类
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {}
自定义接口继承IService接口,则继承了IService接口中的抽象方法,那么在实现类中必然需要实现这些抽象方法,但这些抽象方法太多了,所以就将实现类继承ServiceImpl类,而ServiceImpl类实现了IService接口中的方法,所以实现类就可以简单理解为实现了IService接口中的抽象方法。
3.常用方法
-
getBaseMapper():获取对应 entity 的 BaseMapper
BaseMapper<Employee> mapper = employeeService.getBaseMapper(); System.out.println(mapper == employeeMapper); // true
-
getOne(wrapper):根据 Wrapper,查询一条记录,若结果集是多个会抛出异常,可以添加限制条件 wrapper.last(“LIMIT 1”)
QueryWrapper<Employee> wrapper = new QueryWrapper<>(); wrapper.last("limit 1"); employeeService.getOne(wrapper);
-
list(wrapper):指定条件查询多个
QueryWrapper<Employee> wrapper = new QueryWrapper<>(); wrapper.eq("age", 25); employeeService.list(wrapper).forEach(System.out::println);
-
page(page, wrapper):分页 + 高级查询
-
在启动类中配置分页拦截器(如果没有配置,会查询出全部结果)
// 分页拦截器 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); paginationInnerInterceptor.setOverflow(true); //合理化 interceptor.addInnerInterceptor(paginationInnerInterceptor); return interceptor; }
-
在接口中定义抽象方法
IPage<Employee> query(EmployeeQuery qo);
-
在实现类中实现抽象方法
@Override public IPage<Employee> query(EmployeeQuery qo) { IPage<Employee> page = new Page<>(qo.getCurrentPage(), qo.getPageSize()); //设置分页信息 QueryWrapper<Employee> wrapper = Wrappers.<Employee>query(); //拼接条件 return super.page(page,wrapper); }
-
进行测试
// 需求:查询第2页员工信息, 每页显示3条, 按id排序 // SELECT id,name,password,email,age,admin,dept_id FROM employee LIMIT ?,? @Test public void testPage2() { EmployeeQuery qo = new EmployeeQuery(); qo.setCurrentPage(2); qo.setPageSize(3); QueryWrapper<Object> wrapper = Wrappers.query(); wrapper.orderByAsc("id"); employeeService.query(qo); }
-
4.事务
自定义方法,需要事务管理的则在方法上贴@Transactional注解
mybatis-plus提供的方法,底层已经对需要事务管理的方法贴了@Transactional注解