Mybatis-plus快速入门

本文章基于SpringBoot

Mybatis-plus

简介

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

特性

无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作

强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求

支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错

支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题

支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作

支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )

内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用

内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询

分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库

内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询

内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

优点

1>SQL语句自由控制,较为灵活

2>SQL与业务代码分离,易于阅读与维护

3>提供动态SQL语句,可以根据需求灵活控制

缺点

1>简单的crud操作也必须提供对应SQL语句

2>必须维护大量的xml文件

3>自身功能有限,要拓展只能依赖第三方插件

依赖

<?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</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>1.0.0</version>
​
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <!--SpringBoot版本-->
        <version>2.4.3</version>
        <relativePath/>
    </parent>
​
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>11</java.version>
    </properties>
​
    <dependencies>
        <!--mybatis plus苞米豆依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>
        <!--druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.17</version>
        </dependency>
        <!--mysql数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <!--springboot测试类-->
        <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>

配置4要素和日志

#mysql
​
spring.datasource.url=jdbc:mysql://localhost/mybatis-plus?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
​
spring.datasource.username=root
​
spring.datasource.password=admin
​
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
​
# 配置slq打印日志
​
#logging.level.cn.wolfcode.mp.mapper=debug
​
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

常用注解

@TableName:

当表名与类名不一致时使用,做表名与类名映射

描述:表名注解

作用:指定当前实体类映射哪张数据库表, 默认是跟实体类名一致

@TableName("m_employee")
public class Employee {

@TableId:

在没有明确指定id生成规则时,默认使用雪花算法

描述:主键注解

作用:标记当前属性映射表主键。

其中:type属性指定主键类型

@TableId(value = "id",type = IdType.AUTO)

@TableField:

当列名与属性名不一致使用,做列名与属性名映射。(exist = false):表示该属性不与表中列进行映射

描述:字段注解(非主键)

作用:指定当前属性映射数据库表哪一列, 默认是跟属性名一致

其中:exist属性表示当前属性是否映射数据库列

@TableField(exist = false)
private Department dept;

通用Mapper接口

insert

// insert
// 需求:添加一条用户信息
// 插入一条记录
@Test
public void testSave(){
    // 新建一个实体类并将数据存进去
    Employee employee = new Employee("dafei", "111", "codeingMan@qq.com", 18, false, 1L);
    employeeMapper.insert(employee);
}

update

updateById:

更新条件是id,并且是全量的

拼接规则:

1.实体对象参数属性有值,那么该属性名会拼接sql中

2.实体对象参数属性为基本属性,会有默认值,mybatis-plus认为是有值,参与SQL拼接

解决方案:

1.将基本类型改为包装类型

2.执行查询,再替换,后更新操作步骤

3.部分字段更新--(null,wrapper)

// updateById
// 需求: 将id=20用户名字修改为dafei
// 根据id对数据库进行修改
//1:先查
//2:替换
//3:更新
// 如果直接更新会导致数据丢失,因为updateById方法更新是整个更新的
@Test
public void testUpdateById(){
    Employee employee = employeeMapper.selectById(20L);
    employee.setName("dafei");
    employeeMapper.updateById(employee);
}

update:

更新条件不仅限于id,并且部分列更新

// update
// 需求:更新name=dafei员工年龄为28岁
// 其中:使用UpdateWrapper中的eq方法添加条件,set方法设置改变值
// 注意: 拼接sql时,所有非null 字段都进行set 拼接
@Test
public void testUpdate1(){
    UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
    wrapper.eq("name" , "dafei");
    wrapper.set("age",28);
    employeeMapper.update(null,wrapper);
}
// 需求:更新name=dafei,并且password=1111的员工年龄为18岁
@Test
public void testUpdate2(){
    UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
    wrapper.eq("name","dafei").eq("password","1111").set("age",18);
    employeeMapper.update(null,wrapper);
}

delete

// deleteById
// 需求:删除id=20的员工信息
@Test
public void testDeleteById(){
    employeeMapper.deleteById(20L);
}
// deleteBatchIds
// 需求:删除id=20, id=21的员工信息
// DELETE FROM m_employee WHERE id IN ( ? , ? )
@Test
public void testBatchDelete(){
    // 方法需要传入一个集合
    employeeMapper.deleteBatchIds(Arrays.asList(20L,21L));
}
// deleteByMap
// 需求:删除name=dafei并且age=18的员工信息
// DELETE FROM m_employee WHERE name = ? AND age = ?
@Test
public void testdeleteByMap(){
    // 该方法需要传入一个map集合
    Map<String,Object> map = new HashMap<>();
    map.put("name","dafei");
    map.put("age",18);
    employeeMapper.deleteByMap(map);
}
// delete
// 需求:删除name=dafei并且age=18的员工信息
// DELETE FROM m_employee WHERE (name = ? AND age = ?)
@Test
public void testDelete(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("name","dafei");
    wrapper.eq("age",18);
    employeeMapper.delete(wrapper);
}

select

// selectById
// 需求:查询id=1的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE id=?
@Test
public void testSelectById(){
    System.out.println(employeeMapper.selectById(1L));
}
// selectBatchIds
// 需求:查询id=1,id=2的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE id IN ( ? , ? )
@Test
public void selectBatchIds(){
    System.out.println(employeeMapper.selectBatchIds(Arrays.asList(1L, 2L)));
}
// selectByMap
// 需求: 查询name=dafei, age=18的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE name = ? AND age = ?
@Test
public void testSelectByMap(){
    Map<String,Object> map = new HashMap<>();
    map.put("name","dafei");
    map.put("age",18);
    employeeMapper.selectByMap(map);
}
// selectCount
// 需求: 查询部门号为5的所有的员工个数
// SELECT COUNT( 1 ) FROM m_employee WHERE (dept_id = ?)
@Test
public void testSelectCount(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("dept_id",5L);
    System.out.println(employeeMapper.selectCount(wrapper));
}
// selectList
// 需求: 查询满足条件部门号为5的所有的员工信息, 返回List<Employee>
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (dept_id = ?)
@Test
public void testSelectList(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("dept_id",5L);
    employeeMapper.selectList(wrapper).forEach(System.out::println);
}

selectMaps

当查询数据无法封装成对象时使用selectMaps

// selectMaps
// 需求: 查询满足条件部门号为5的所有的员工信息, 返回List<Map<String, Object>>  底层将每条数据封装成HashMap
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (dept_id = ?)
@Test
public void testSelectMaps(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("dept_id",5L);
    employeeMapper.selectMaps(wrapper).forEach(System.out::println);
}

分页

// SelectPage
// 需求:查询第二页员工数据, 每页显示3条, (分页返回的数据是实体对象)
// 步骤1:配置分页插件,在启动类中配置分页拦截器
@SpringBootApplication
@MapperScan("cn.wolfcode.mp.mapper")
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class,args);
​
    }
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        paginationInnerInterceptor.setOverflow(true); //合理化
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }
}
// 步骤2:编写分页代码
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee LIMIT ?,?
@Test
public void testSelectPage(){
    // IPage集合需要两个参数,一个是第几页,一个是每页显示多少条
    IPage<Employee> page = new Page<>(2,3);
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    // 该方法需要两个参数,一个是Page集合,一个是Wrapper设置条件,无条件等价于null
    IPage<Employee> iPage = employeeMapper.selectPage(page, wrapper);
    System.out.println("当前页:" + iPage.getCurrent());
    System.out.println("每页显示条数:" + iPage.getSize());
    System.out.println("总页数:" + iPage.getPages());
    System.out.println("总数:" + iPage.getTotal());
    System.out.println("当前页数据:");
    iPage.getRecords().forEach(System.out::println);
}

条件构造器

继承体系

 

更新操作

UpdateWapper

// UpdateWrapper:set
// 需求:将id=1的员工name改为dafei
// 注意:set方法中第一个参数是开关,true:执行该方法,false:不执行该方法
// UPDATE m_employee SET name=? WHERE (id = ?)
@Test
public void testUpdate1(){
    UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
    wrapper.eq("id",1L);
    wrapper.set(true,"name","dafei");
    employeeMapper.update(null,wrapper);
}
​
// UpdateWrapper:setSql
// 需求:将id=2的用户name改为dafei
// 注意:setSql方法中第一个参数是开关,true:执行该方法,false:不执行该方法
// UPDATE m_employee SET name = 'dafei' WHERE (id = ?)
@Test
public void testUpdate2(){
    UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
    wrapper.eq("id",2L).setSql(true,"name = 'dafei'");
    employeeMapper.update(null,wrapper);
}

QueryWapper

// QueryWrapper
// 需求:查询name=dafei, age=18的用户
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (name = ? AND age = ?)
@Test
public void testQuery1(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("name","dafei").eq("age",18);
    employeeMapper.selectList(wrapper).forEach(System.err::println);
}

LambdaUpdateWrapper

// LambdaUpdateWrapper:set
// 需求:将id=3的员工name改为dafei
// 注意:set方法中第一个参数是开关,true:执行该方法,false:不执行该方法
// UPDATE m_employee SET name=? WHERE (id = ?)
@Test
public void testUpdate3(){
    LambdaUpdateWrapper<Employee> wrapper = new LambdaUpdateWrapper<>();
    wrapper.eq(Employee::getId,3L).set(true,Employee::getName,"dafei");
    employeeMapper.update(null,wrapper);
}

LambdaQueryWrapper

// LambdaQueryWrapper
// 需求:查询name=dafei, age=18的用户
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (name = ? AND age = ?)
@Test
public void testQuery2(){
    LambdaUpdateWrapper<Employee> wrapper = new LambdaUpdateWrapper<>();
    wrapper.eq(Employee::getName,"dafei").eq(Employee::getAge,18);
    employeeMapper.selectList(wrapper).forEach(System.err::println);
}

高级查询

列投影:select

// select
// 需求:查询所有员工, 返回员工name, age列
// SELECT name,age FROM m_employee
@Test
public void testQuery1(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.select("name,age");     // SQL片段,是直接插入到SQL语句的
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// 需求:查询所有员工, 返回员工以a字母开头的列
// SELECT id,age,admin FROM m_employee
@Test
public void testQuery2(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.select(Employee.class,f->f.getProperty().startsWith("a"));
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

排序

orderByAsc/orderByDesc

// orderByAsc
// 需求:查询所有员工信息按age正序排, 如果age一样, 按id正序排
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee ORDER BY age,id ASC
@Test
public void testQuery3(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.orderByAsc("age,id");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
//orderByDesc
// 需求:查询所有员工信息按age逆序排, 如果age一样, 按id逆序排
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee ORDER BY age,id DESC
@Test
public void testQuery4(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.orderByDesc("age,id");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

orderBy

// orderBy
// 需求:查询所有员工信息按age正序排, 如果age一样, 按id正序排
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee ORDER BY age,id ASC
@Test
public void testQuery5(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    // 第一个参数是开关,true:执行该方法,false:不执行该方法。
    // 第二个参数是声明是否正序,true:正排序,false:逆排序
    wrapper.orderBy(true,true,"age,id");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// orderBy
// 需求:查询所有员工信息按age正序排, 如果age一样, 按id倒序排
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee ORDER BY age ASC,id DESC
@Test
public void testQuery6(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    // 第一个参数是开关,true:执行该方法,false:不执行该方法。
    // 第二个参数是声明是否正序,true:正排序,false:逆排序
    wrapper.orderBy(true,true,"age")
            .orderBy(true,false,"id");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

分组查询

groupBy

// groupBy
// 需求:以部门id进行分组查询,查每个部门员工个数
// 注意:一般group by 会配合count()来使用,不然会报错。
// SELECT dept_id,count(id) count FROM m_employee GROUP BY dept_id
@Test
public void testQuery7(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.select("dept_id,count(id) count");
    wrapper.groupBy("dept_id");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

having

// having
// 需求: 以部门id进行分组查询,查每个部门员工个数, 将大于3人的部门过滤出来
// SELECT dept_id,count(id) count FROM m_employee GROUP BY dept_id HAVING count > 3
@Test
public void testQuery8(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.select("dept_id,count(id) count").groupBy("dept_id")    //.having("count > {0}",3);
            .having("count > 3");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

条件查询

比较运算符

allEq/eq/ne

// allEq
// 需求:查询name=dafei, age=18的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (name = ? AND age = ?)
@Test
public void testQuery9(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    Map<String,Object> map = new HashMap<>();
    map.put("name","dafei");
    map.put("age",18);
    wrapper.allEq(map);
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// 需求:查询满足条件员工信息, 注意传入的map条件中, 包含a的列才参与条件查询
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (name = ? AND age = ?)
@Test
public void testQuery10(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    Map<String,Object> map = new HashMap<>();
    map.put("name", "dafei");
    map.put("age", 18);
    wrapper.allEq((k, v)-> k.contains("a"), map);
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// eq
// 需求:查询name=dafei员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (name = ?)
@Test
public void testQuery11(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("name","dafei");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// ne
// 需求:查询name !=dafei员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (name <> ?)
// <> 等价于 !=
@Test
public void testQuery12(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.ne("name","dafei");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

gt/ge/lt/le

// gt
// 需求:查询age 大于18岁员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (age > ?)
@Test
public void testQuery13(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.gt("age",18);
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// ge
// 需求:查询age 大于等于18岁员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (age >= ?)
@Test
public void testQuery14(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.ge("age",18);
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// lt
// 需求:查询age 小于18岁员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (age < ?)
@Test
public void testQuery15(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.lt("age",18);
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// le
// 需求:查询age 小于等于18岁员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (age <= ?)
@Test
public void testQuery16(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.le("age",18);
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

between/notBetween

// between
// 需求:查询年龄介于18~30岁的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (age BETWEEN ? AND ?)
@Test
public void testQuery17(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.between("age",18,30);
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// notBetween
// 需求:查询年龄小于18或者大于30岁的员工信息【用notBetween实现】
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (age NOT BETWEEN ? AND ?)
@Test
public void testQuery18(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.notBetween("age",18,30);
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

isNull/isNotNull

// isNull
// 需求: 查询dept_id 为null 员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (dept_id IS NULL)
@Test
public void testQuery19(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.isNull("dept_id");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// isNotNull
// 需求: 查询dept_id 为不为null 员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (dept_id IS NOT NULL)
@Test
public void testQuery20(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.isNotNull("dept_id");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

in/notIn/inSql/notInSql

// in
// 需求: 查询id为1, 2 的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (id IN (?,?))
@Test
public void testQuery21(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.in("id", Arrays.asList(1L,2L));
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// notIn
// 需求: 查询id不为1, 2 的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (id NOT IN (?,?))
@Test
public void testQuery22(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.notIn("id", Arrays.asList(1L,2L));
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// inSql
// 需求: 查询id为1, 2 的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (id IN (1,2))
@Test
public void testQuery23(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.inSql("id","1,2");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// notInSql
// 需求: 查询id不为1, 2 的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (id NOT IN (1,2))
@Test
public void testQuery24(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.notInSql("id", "1,2 ");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

模糊查询

like/notLike

// like
// 需求: 查询name中含有fei字样的员工
// 注意: 方法会自动帮我们在参数的前后加上%符号,无需我们添加
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (name LIKE ?)
@Test
public void testQuery25(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.like("name","fei");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// notLike
// 需求: 查询name中不含有fei字样的员工
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (name NOT LIKE ?)
@Test
public void testQuery26(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.notLike("name","fei");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

likeLeft/likeRight

// likeLeft
// 需求: 查询name以fei结尾的员工信息
// 注意: likeLeft方法会已%为锚点,自动将%加在参数的左边
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (name LIKE ?)
@Test
public void testQuery27(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.likeLeft("name","fei");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// likeRight
// 需求: 查询姓李的员工信息
// 注意: likeRight方法会已%为锚点,自动将%加在参数的右边
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (name LIKE ?)
@Test
public void testQuery28(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.likeRight("name","李");
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

逻辑运算符

or

// or
// 需求: 查询age = 18 或者 name=dafei 或者 id =1 的用户
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (age = ? OR name = ? OR id = ?)
@Test
public void testQuery29(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("age",18).or().eq("name","dafei").or().eq("id",1);
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// 需求:查询name含有fei字样的,或者 年龄在18到30之间的用户,不能用between
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (name LIKE ? OR (age >= ? AND age <= ?))
@Test
public void testQuery30(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.like("name","fei").or(
            wp->wp.ge("age",18).le("age",30)
    );
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

and

// and : 默认是and操作
// 需求:查询年龄介于18~30岁的员工信息
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (age >= ? AND age <= ?)
@Test
public void testQuery31(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.ge("age",18).le("age",30);
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}
// 嵌套and:
// 需求:查询name含有fei字样的并且 年龄在小于18或者大于30的用户
// SELECT id,name,password,email,age,admin,dept_id FROM m_employee WHERE (name LIKE ? AND (age < ? OR age > ?))
@Test
public void testQuery32(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.like("name","fei").and(
            wp->wp.lt("age",18).or().gt("age",30)
    );
    employeeMapper.selectMaps(wrapper).forEach(System.err::println);
}

自定义SQL

mapper.xml方式

单表查询,关联查询

<--步骤1:在XxxMapper.xml中编写数据库语句-->
<mapper namespace="cn.wolfcode.mp.mapper.EmployeeMapper">
    <resultMap id="BaseResultMap" type="cn.wolfcode.mp.domain.Employee" >
        <id column="id" property="id" jdbcType="BIGINT" />
        <result column="name" property="name" jdbcType="VARCHAR" />
        <result column="password" property="password" jdbcType="VARCHAR" />
        <result column="email" property="email" jdbcType="VARCHAR" />
        <result column="age" property="age" jdbcType="INTEGER" />
        <result column="admin" property="admin" jdbcType="BIT" />
        <result column="dept_id" property="deptId" jdbcType="BIGINT" />
        <association property="dept" javaType="cn.wolfcode.mp.domain.Department" columnPrefix="d_">
            <result column="id" property="id"/>
            <result column="name" property="name"/>
            <result column="sn" property="sn"/>
        </association>
    </resultMap>
    <select id="listByXmlSingle" resultMap="BaseResultMap">
        select id, name, password, email, age, admin, dept_id from m_employee
    </select>
    <select id="listByXmlJoin" resultMap="BaseResultMap">
        select e.id, e.name, e.password, e.email, e.age, e.admin, e.dept_id, d.id d_id, d.name d_name, d.sn d_sn
        from m_employee e join m_department d on e.dept_id = d.id
    </select>
</mapper>
//步骤2:在Mapper接口编写方法

// 单表
List<Employee> listByXmlSingle();
// 关联
List<Employee>  listByXmlJoin();
// 自定义SQL语句
// 单表查询

//步骤3:编写测试类
@Test
public void testQuery33(){
    employeeMapper.listByXmlSingle().forEach(System.err::println);
}
// 多表查询
@Test
public void testQuery34(){
    employeeMapper.listByXmlJoin().forEach(System.err::println);
}

注解方式【拓展】

单表查询,关联查询

在Mapper接口的方法上贴上@Select注解和@Results注解

@Select("select e.* from m_employee e")
List<Employee> listByAnnoSingle();
​
@Select("select e.*, d.id d_id, d.name d_name, d.sn d_sn from m_employee e left join m_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> listByAnnoJoin();
// 自定义SQL语句:注解方式
// 单表查询
@Test
public void testQuery35(){
    employeeMapper.listByAnnoSingle().forEach(System.err::println);
}
// 多表查询
@Test
public void testQuery36(){
    employeeMapper.listByAnnoJoin().forEach(System.err::println);
}

通用Service接口

通用方式

自定义接口:

自定义接口继承 IService 接口

明确指定泛型,当前接口操作实体对象:Employee

// 自定义服务接口继承IService接口
// 注意IService接口泛型:
// 泛型:实体类
public interface IEmployeeService extends IService<Employee> {
}

服务层接口实现类:

1.自定义一个类继承 ServiceImpl 实现自定义服务接口 IEmployeeService

2.在ServiceImpl上明确指定2两个泛型:

当前操作实体对象对应Mapper接口EmployeeMapper

当前操作实体对象Employee

// 实现类继承IService接口的实现类ServiceImpl同时实现自定义接口
// 注意ServiceImpl实现类泛型:
// 泛型1:实体类的mapper接口
// 泛型2:实体类
@Service
@Transactional
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {
}

常用方法

getBaseMapper()

获取引用的XxxxMapper对象

// getBaseMapper:
// 获取当前接口引用的xxxMapper对象
@Test
public void testService1(){
    employeeService.getBaseMapper().selectList(null).forEach(System.err::println);
    System.out.println(employeeService.getBaseMapper() == employeeMapper);
}

getOne(wrapper)

指定条件查询单个, 结果数据超过1个报错

// getOne:
// 指定条件查询单个, 结果数据超过1个报错
@Test
public void testService2(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("id",1L);
    System.out.println(employeeService.getOne(wrapper));
}

list(wrapper)

指定条件查询多个

// list:
// 指定条件查询多个
@Test
public void testService3(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("name","dafei");
    employeeService.list(wrapper).forEach(System.err::println);
}

page(page, wrapper)

分页+高级查询

启动类:

//步骤1:配置分页插件
//分页
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        paginationInnerInterceptor.setOverflow(true); //合理化
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }

 业务层XxxServiceImpl:

//步骤2:编写分页代码
@Override
public IPage<Employee> page(EmployeeQuery qo) {
    IPage<Employee> page = new Page<>(qo.getCurrentPage(),qo.getPageSize());
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.like(StringUtils.hasText(qo.getKeyWord()),"name",qo.getKeyWord());
    return super.page(page,wrapper);
}

测试类: 

// 分页
// 需求:查询第2页员工信息, 每页显示3条
@Test
public void testPage1(){
    EmployeeQuery query = new EmployeeQuery();
    query.setCurrentPage(2);
    query.setPageSize(3);
    query.setKeyWord("fei");
    IPage<Employee> iPage = employeeService.page(query);
    System.out.println("当前页码:" + iPage.getCurrent());
    System.out.println("每页显示数量:" + iPage.getSize());
    System.out.println("总记录数:" + iPage.getTotal());
    System.out.println("总页数:" + iPage.getPages());
    System.out.println("数据:");
    iPage.getRecords().forEach(System.err::println);
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值