Mybatis-Plus学习笔记

目录

1. Mybatis-Plus简介

1.1 Mybatis-Plus介绍

1.2 代码以及文档

1.3 特性

1.4 框架结构

1.5 作者

2. 快速入门

2.0 准备工作

2.1 Mybatis整合Mybatis-Plus

2.1.1 原生Mybatis查询

2.1.2 使用Mybatis-Plus查询

2.2 Spring&Mybatis整合Mybatis-Plus

2.3 SpringBoot、Mybatis整合Mybatis-Plus

3. 通用增删改查

3.1 插入操作

3.1.1 insert

3.1.2 @TableId

3.1.3 @TableField

3.2 更新操作

3.2.1 updateById

3.2.2 update

3.3 删除操作

3.3.1 deleteById

3.3.2 deleteByMap

3.3.3 delete

3.3.4 deleteBatchIds

3.4 查询操作

3.4.1 selectById

3.4.2 selectBatchIds

3.4.3 selectOne

3.4.4 selectCount

3.4.5 selectList

3.4.6 selectPage

4. 配置

4.1 基本配置

4.1.1 configLocation

4.1.2 mapperLocations

4.1.3 typeAliasesPackage

4.2 进阶配置

4.2.1 mapUnderscoreToCamelCase

4.2.2 cacheEnabled

4.3 DB策略配置

4.3.1 idType

4.3.2 tablePrefix

5. 条件构造器

5.1 allEq

5.2 基本比较操作

5.3 模糊查询

5.4 排序

5.5 逻辑查询

5.6 select

6. ActiveRecord

6.1 开启ActiveRecord

6.2 根据id查询

6.3 插入数据

6.4 更新数据

6.5 删除数据

6.6 根据条件查询

7. 其他

7.1 SQL注入器

7.1.1 编写MyBaseMapper

7.1.2 编写MySqlInjector

7.1.3 编写FindAll

7.1.4 注册到Spring容器

7.1.5 进行测试

7.2 自动填充功能

7.2.1 添加@TableField注解

7.2.2  编写MyMetaObjectHandler

7.2.3  测试

7.3 逻辑删除

7.3.1 修改表结构

7.3.2 配置

7.3.3 测试

7.4 通用枚举

7.4.1 修改表结构

7.4.2 定义枚举

 7.4.3 配置

7.4.4 修改实体类

7.4.5 测试


1. Mybatis-Plus简介

1.1 Mybatis-Plus介绍

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

官网:mybatis.plusRedirect

1.2 代码以及文档

文档地址:mybatis.plus

源码地址:https://github.com/baomidou/mybatis-plus

1.3 特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 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.4 框架结构

1.5 作者

2. 快速入门

对于Mybatis整合MP有常常有三种用法,分别是Mybatis+MP、Spring+Mybatis+MP、Spring Boot+Mybatis+MP。

2.0 准备工作

建立测试用的数据库和表,SQL以及如下:

/*
Navicat MySQL Data Transfer

Source Server         : MYSQL5_3306
Source Server Version : 50518
Source Host           : localhost:3306
Source Database       : db_mp_test

Target Server Type    : MYSQL
Target Server Version : 50518
File Encoding         : 65001

Date: 2021-05-23 10:45:35
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) NOT NULL,
  `password` varchar(20) NOT NULL,
  `name` varchar(20) NOT NULL,
  `age` int(11) NOT NULL,
  `email` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES ('1', 'zhangsan', '123456', '张三', '18', 'zhangsan@qq.com');
INSERT INTO `tb_user` VALUES ('2', 'lisi', '123456', '李四', '20', 'lisi@qq.com');
INSERT INTO `tb_user` VALUES ('3', 'wangwu', '123456', '王五', '21', 'wangwu@qq.com');
INSERT INTO `tb_user` VALUES ('4', 'zhaoliu', '654321', '赵六', '19', 'zhaoliu@qq.com');
INSERT INTO `tb_user` VALUES ('5', 'sunqi', '852369', '孙七', '22', 'sunqi@qq.com');

2.1 Mybatis整合Mybatis-Plus

2.1.1 原生Mybatis查询

第一步,创建一个基于maven的JavaWeb项目

第二步,导入相关的依赖

mybatis-plus的坐标如下:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>3.4.3</version>
</dependency>

导入其他需要的依赖

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.22</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>

第三步,配置日志文件log4j.properties在resources目录下

log4j.rootLogger=DEBUG,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%t][%c]-[%p]%m%n

第四步,在resources目录下创建mybatis的核心配置文件sqlMapConfig.xml文件,并且配置数据源

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTDConfig3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db_mp_test"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

第五步,编写User实体类

public class User {
    private Long id;
    private String username;
    private String password;
    private String name;
    private Integer age;
    private String email;
    // 无参和全参构造器、get和set方法、toString方法
}

第六步,创建UserMapper接口

public interface UserMapper {
    List<User> findAll();
}

第六步,创建接口对应的UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTDMapper3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.demo.mapper.UserMapper">
    <select id="findAll" resultType="com.demo.bean.User">
        select * from tb_user
    </select>
</mapper>

在SqlMapConfig.xml配置文件中添加此映射

第七步,编写TestMybatis

public class TestMybatis {
    @Test
    public void testFindAll() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 获取UserMapper接口
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 执行findAll方法
        List<User> userList = mapper.findAll();
        // 打印结果
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

控制台打印如下:

2.1.2 使用Mybatis-Plus查询

在原生的Mybatis基础上使用Mybatis-Plus查询只需要进行两步操作:

第一步,将UserMapper继承BaseMapper<T>,将拥有BaseMapper中的所有方法。

第二步,将原来的SqlSessionFactoryBuilder替换成MybatisSqlSessionFactoryBuilder进行构建

public class TestMybatisPlus {
    @Test
    public void testFindAll() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 获取UserMapper接口
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 执行findAll方法
        List<User> userList = mapper.findAll();
        // 打印结果
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

打印结果如下:

本节源码请参考:GitHub的Demo

2.2 Spring&Mybatis整合Mybatis-Plus

引入了spring框架,数据源、构建工作交由Spring来管理。

第一步,创建一个基于web的maven项目并导入相关的包

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>3.4.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.22</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.4</version>
        </dependency>

第二步,编写jdbc.properties,将链接数据库的参数配置在里面

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/db_mp_test
jdbc.username=root
jdbc.password=root

第二步,编写spring的配置文件applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <!--引入properties配置文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--定义数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--这里使用MybatisSqlSessionFactory,完成Spring与Mybatis-Plus的整合-->
    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--扫描Mapper接口类,使用的是Mybatis原生的扫描器-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.demo.mapper"/>
    </bean>
</beans>

第三步,编写User实体类,使用@TableName("tb_user")注解映射数据库表和实体类的关系

@TableName("tb_user")
public class User {
    private Long id;
    private String username;
    private String password;
    private String name;
    private Integer age;
    private String email;
    // 无参和全参构造器、get和set方法、toString方法
}

第四步,创建UserMapper接口,只需要继承BaseMapper<T>类,不需要写任何方法

public interface UserMapper extends BaseMapper<User> {

}

第五步,编写测试用例

public class TestMybatisPlus {

    @Test
    public void testFindAll() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        List<User> userList = userMapper.selectList(null);
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

打印结果如下:

在本例中没有写Mapper.xml,也没有写mybatis的配置文件了。

本节源码参考:GitHub的Demo

2.3 SpringBoot、Mybatis整合Mybatis-Plus

第一步,创建一个基于web的maven工程,然后导入相关的依赖坐标

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!--mybatis-plus的springboot支持-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.1</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>
        <!--日志-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>

注意,还需要在pom.xml中引入parent

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
    </parent>

第二步,日志文件log4j.properties如下,在resources目录下

log4j.rootLogger=DEBUG,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%t][%c]-[%p]%m%n

第三步,编写springboot的配置文件application.properties

spring.application.name=springboot-mybatisplus

# 配置数据源连接参数
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db_mp_test
spring.datasource.username=root
spring.datasource.password=root

第四步,编写实体类User,使用@TableName("tb_user")注解完成实体类和数据库表的映射

@TableName("tb_user")
public class User {
    private Long id;
    private String username;
    private String password;
    private String name;
    private Integer age;
    private String email;
    // 无参和全参构造器、get和set方法、toString方法
}

第四步,创建UserMapper接口,只需要继承BaseMapper<T>类,不需要写任何方法

public interface UserMapper extends BaseMapper<User> {

}

第五步,编写springboot启动类

@MapperScan("com.demo.mapper")// 设置mapper接口的扫描包
@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}

第六步,编写测试类进行测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestMybatisPlus {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testFindAll() {
        List<User> userList = userMapper.selectList(null);
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

打印结果如下:

本节源码参考:GitHub的Demo

3. 通用增删改查

通过前面的学习,我们了解到通过继承BaseMapper就可以获取到各种各样的单表操作,接下来我们将详细讲解这些操作。

3.1 插入操作

3.1.1 insert

在BaseMapper中的insert方法如下:

// 插入一条记录,返回受影响的行数
int insert(T entity);

测试方法如下:

public class TestMybatisPlus {

    @Test
    public void testInsert() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 创建测试实体类并封装数据
        User user = new User();
        user.setUsername("tangseng");
        user.setPassword("123456");
        user.setName("唐僧");
        user.setAge(18);
        user.setEmail("tangseng@qq.com");
        // 调用insert方法进行插入操作,返回受影响的行数
        int result = userMapper.insert(user);
        // 打印结果
        System.out.println("受影响行数:" + result);// 打印受影响行数
        System.out.println(user.getId());// 自增后的id会回填到对象中
    }
}

3.1.2 @TableId

虽然数据写入到数据库中,但是id值不正确,我们期望数据库id主键自增长,实际是MybatisPlus生成了id的值写入到了数据库中。

但我们可以通过设置id的生成策略来进行设置。

Mybatis支持的id策略,可以查看IdType枚举类。

public enum IdType {
    AUTO(0),// 数据库ID自增
    NONE(1),//该类型为未设置主键类型
    INPUT(2),// 用户输入ID
    ASSIGN_ID(3),
    ASSIGN_UUID(4);

    private final int key;

    private IdType(int key) {
        this.key = key;
    }

    public int getKey() {
        return this.key;
    }
}

所以,如果我们想要id值自增长,可以在实体类的id字段上添加@TableId(type=IdType.AUTO)注解来指定id类型为自增长。

@TableName("tb_user")
public class User {
    @TableId(type = IdType.AUTO)// 设置id字段为自增长
    private Long id;
    private String username;
    private String password;
    private String name;
    private Integer age;
    private String email;
    // 无参和全参构造器、get和set方法、toString方法
}

再来执行测试,就会发现id字段是自增长了,并且这条插入数据的id会封装在User对象中返回。

3.1.3 @TableField

在MybatisPlus中通过@TableField注解可以指定字段的一些属性,常解决的问题有:

  • 对象中的属性名和数据库表中的字段名不一致的问题,如非驼峰。
  • 对象中属性字段在数据库表中不存在的问题。

3.2 更新操作

更新操作有2种,一种是根据id更新,另一种是根据条件更新。

3.2.1 updateById

方法的定义是:

// 根据ID进行更新数据库表记录,返回受影响行数
int updateById(@Param(Constants.ENTITY) T entity);

使用示例如下:

    @Test
    public void testUpdateById() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 创建要更新的字段,将主键id字段和其他要更新的字段封装在对象中
        User user = new User();
        user.setId(4L);// 待更新的主键ID
        user.setPassword("abcdef");// 更新的字段
        user.setAge(22);// 更新的字段
        // 调用updateById方法进行更新操作,返回受影响的行数
        int result = userMapper.updateById(user);
        System.out.println("受影响的行数:" + result);
    }

3.2.2 update

根据条件更新的方法如下:

// 根据where多条件更新记录
// 有两个参数:第一个参数是entity指的是实体对象(set 条件值,可以为null)
// 第二个参数updateWrapper是实体对象封装操作类(可以为null,里面的entity用于生成where语句)
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);

使用示例如下:

    @Test
    public void testUpdate() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 创建要更新的字段,将主键id字段和其他要更新的字段封装在对象中
        User user = new User();
        user.setPassword("abcdef");// 更新的字段
        user.setAge(22);// 更新的字段
        // 添加更新的条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        wrapper.eq("id", 6);
        // 执行更新操作
        // 第一个参数是设置SQL语句中的set后面的参数(如set username='zhangsan',age=13)
        // 第二个参数是设置SQL语句中的where后面的参数(如where id=3 and name='张三')
        int result = userMapper.update(user, wrapper);
        System.out.println("受影响的行数:" + result);
    }

也可以通过UpdateWrapper类来封装条件和更新的参数。

    @Test
    public void testUpdate2() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 设置更新的条件及更新的字段
        UpdateWrapper<User> wrapper = new UpdateWrapper<User>();
        // eq相当于设置where后面的条件;set相当于设置set后面的字段
        wrapper.eq("id", 6).set("password", "123456");
        // 执行更新操作
        int result = userMapper.update(null, wrapper);
        System.out.println("受影响的行数:" + result);
    }

3.3 删除操作

3.3.1 deleteById

方法如下:

// 根据id进行删除记录,返回受影响的行数
int deleteById(Serializable id);

使用示例如下:

    @Test
    public void testDeleteById() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 执行删除操作
        int result = userMapper.deleteById(5L);
        System.out.println("受影响的行数:" + result);
    }

3.3.2 deleteByMap

方法定义如下:

// 根据条件删除记录,columnMap是一个Map集合,存储着条件字段和对应的值
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

示例如下:

    @Test
    public void testDeleteByMap() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 将条件放到集合中
        Map<String, Object> columnMap = new HashMap<String, Object>();
        columnMap.put("age", "20");
        columnMap.put("name", "张三");
        // 执行多条件删除操作,多个条件之间为AND关系
        int result = userMapper.deleteByMap(columnMap);
        System.out.println("受影响的行数:" + result);
    }

3.3.3 delete

方法定义:

// 根据实体类条件,删除记录,wrapper就是实体类对象封装操作类,可以为null
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);

示例如下:

    @Test
    public void testDelete() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 封装条件
        User user = new User();
        user.setAge(20);
        user.setId(3L);
        user.setName("李四");
        // 将实体对象进行封装,包装为操作条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>(user);
        // 执行删除操作,多个条件之间为AND关系
        int result = userMapper.delete(wrapper);
        System.out.println("受影响的行数:" + result);
    }

3.3.4 deleteBatchIds

批量按照id进行删除,方法定义如下:

// 删除,根据id批量删除
int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);

示例如下:

    @Test
    public void testDeleteBatchIds() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 将要删除的id放到集合中
        List<Long> list = new ArrayList<Long>();
        list.add(1L);
        list.add(12L);
        list.add(22L);
        // 根据id集合批量删除
        int result = userMapper.deleteBatchIds(list);
        System.out.println("受影响的行数:" + result);
    }

3.4 查询操作

3.4.1 selectById

方法定义如下:

// 根据id进行查询
T selectById(Serializable id);

示例如下:

    @Test
    public void testSelectById() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 根据id进行查询
        User user = userMapper.selectById(2L);
        System.out.println(user);
    }

3.4.2 selectBatchIds

方法定义:

// 根据id集合批量查询,返回实体类集合
List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);

示例:

    @Test
    public void testSelectBatchIds() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 根据id集合进行查询
        List<Long> idList = new ArrayList<Long>();
        idList.add(1L);
        idList.add(2L);
        idList.add(3L);
        idList.add(4L);
        // 调用方法进行查询
        List<User> userList = userMapper.selectBatchIds(idList);
        for (User user : userList) {
            System.out.println(user);
        }
    }

3.4.3 selectOne

方法如下:

// 查询一条数据
T selectOne(@Param("ew") Wrapper<T> queryWrapper);

示例:

    @Test
    public void testSelectOne() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 设定条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        wrapper.eq("name", "李四");
        // 根据条件查询一条数据,如果结果超过一条就会报错
        User user = userMapper.selectOne(wrapper);
        System.out.println(user);
    }

3.4.4 selectCount

方法定义:

// 根据wrapper条件,查询总记录数,其中参数可以为null
Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);

示例如下:

    @Test
    public void testSelectCount() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 设定条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        wrapper.gt("age", 15);// 查询年龄大于15岁的人
        // 根据条件查询记录总数
        Integer count = userMapper.selectCount(wrapper);
        System.out.println("记录总数:" + count);
    }

3.4.5 selectList

方法定义:

// 根据条件查询符合条件的全部记录
List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);

示例:

    @Test
    public void testSelectList() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 设定条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        wrapper.gt("age", 15);// 查询年龄大于15岁的人
        // 根据条件查询记录
        List<User> userList = userMapper.selectList(wrapper);
        for (User user : userList) {
            System.out.println(user);
        }
    }

3.4.6 selectPage

该方法是分页查询,方法的定义:

// 根据条件分页查询记录,第一个参数分页查询条件,第二个参数为对象封装操作类(可以为null)
IPage<T> selectPage(IPage<T> page, @Param("ew") Wrapper<T> queryWrapper);

在使用该方法之前,现需要配置分页插件,如果是spring整合MybatisPlus,则需要在spring的核心配置文件中添加如下内容:

    <!--这里使用MybatisSqlSessionFactory,完成Spring与Mybatis-Plus的整合-->
    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- spring xml 方式 -->
        <property name="plugins">
            <array>
                <bean class="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor">
                    <!-- COUNT SQL 解析.可以没有 -->
                    <property name="countSqlParser" ref="countSqlParser"/>
                </bean>
            </array>
        </property>
    </bean>
    <bean id="countSqlParser" class="com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize">
        <!-- 设置为 true 可以优化部分 left join 的sql -->
        <property name="optimizeJoin" value="true"/>
    </bean>

如果是SpringBoot整合MybatisPlus则需要创建一个配置类,类中如下内容:

@Configuration
@MapperScan("com.demo.mapper")
public class CustomMyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(paginationInnerInterceptor());
        return interceptor;
    }

    @Bean
    public PaginationInnerInterceptor paginationInnerInterceptor() {
        PaginationInnerInterceptor page = new PaginationInnerInterceptor();
        page.setDbType(DbType.MYSQL);
        return page;
    }
}

示例如下:

    @Test
    public void testSelectPage() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 设定分页参数,第一个参数是页码(从1开始),第二个参数是页显示条数
        Page<User> page = new Page<User>(1L, 2L);
        // 设定筛选条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        wrapper.gt("age", 15);// 查询年龄大于15岁的人
        // 根据条件查询记录
        IPage<User> userPage = userMapper.selectPage(page, null);
        System.out.println("数据总条数:" + userPage.getTotal());
        System.out.println("总页数:" + userPage.getPages());
        // 打印分页记录
        List<User> userList = userPage.getRecords();// 获取分页记录数
        for (User user : userList) {
            System.out.println(user);
        }
    }

打印结果如下:

本节源码参考:GitHub的Demo

4. 配置

Mybatis-Plus各种配置的官方参考文档:mybatis.plus

4.1 基本配置

4.1.1 configLocation

MyBatis 配置文件位置,如果您有单独的 MyBatis 配置,请将其路径配置到 configLocation 中。 MyBatisConfiguration 的具体内容请参考MyBatis 官方文档。

spring整合mybatis-plus,SqlMapConfig.xml配置文件是mybatis的配置文件

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
    <property name="configLocation" value="classpath:SqlMapConfig.xml"/>
</bean>

springboot整合mybatis-plus,需要在application.properties中配置:

mybatis-plus.config-location = classpath:SqlMapConfig.xml

4.1.2 mapperLocations

MyBatis Mapper 所对应的 XML 文件位置,如果您在 Mapper 中有自定义方法(XML 中有自定义实现),需要进行该配置,告诉 Mapper 所对应的 XML 文件位置。

spring整合mybatis-plus:

    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
        <property name="mapperLocations" value="classpath*:com/demo/mapper/*.xml"/>
    </bean>

springboot整合mybatis-plus,需要在application.properties中配置:

mybatis-plus.mapper-locations = classpath*:com/demo/mapper/*.xml

注意:maven多模块的扫描路径以classpath*:开头,即加载多个jar包下的XML文件。

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.demo.mapper.UserMapper">
    <select id="findAll" resultType="com.demo.bean.User">
        select * from tb_user
    </select>
</mapper>

UserMapper.java

public interface UserMapper extends BaseMapper<User> {
    List<User> findAll();
}

进行测试

    @Test
    public void testFindAll(){
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        List<User> all = userMapper.findAll();
        for (User user : all) {
            System.out.println(user);
        }
    }

4.1.3 typeAliasesPackage

MyBaits 别名包扫描路径,通过该属性可以给包中的类注册别名,注册后在 Mapper 对应的 XML 文件中可以直接使用类名,而不用使用全限定的类名(即 XML 中调用的时候不用包含包名)。

spring整合mybatis-plus:

    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
        <property name="typeAliasesPackage" value="com.demo.bean"/>
    </bean>

 springboot整合mybatis-plus,需要在application.properties中配置:

mybatis-plus.type-aliases-package = com.demo.bean

注意,这里IDEA工具会爆红,但是代码是能够运行成功的,因为已经成功配置了的。

4.2 进阶配置

本部分(Configuration)的配置大都为 MyBatis 原生支持的配置,这意味着您可以通过 MyBatis XML 配置文件的形式进行配置。

4.2.1 mapUnderscoreToCamelCase

该配置表示十分开启自动驼峰命名规则(camel case)映射,即从数据库列名如user_name到Java属性名userName(驼峰命名)的映射。

该属性是一个Boolean类型,默认值是true,表示开启了自动驼峰命名规则映射。

注意:此属性在 MyBatis 中原默认值为 false,在 MyBatis-Plus 中,此属性也将用于生成最终的 SQL 的 select body如果您的数据库命名符合规则无需使用@TableField注解指定数据库字段名。

springboot整合mybatis-plus,需要在application.properties中配置:

#关闭自动驼峰映射,该参数不能和mybatis-plus.config-location同时存在
mybatis-plus.configuration.map-underscore-to-camel-case=false

4.2.2 cacheEnabled

全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存,默认为 true。

springboot配置示例:

mybatis-plus.configuration.cache-enabled=false

4.3 DB策略配置

4.3.1 idType

全局默认主键类型,设置后,即可省略实体对象中的@TableId(type = IdType.AUTO)配置。

springboot整合mybatis-plus,需要在application.properties中配置:

mybatis-plus.global-config.db-config.id-type=auto

spring整合mybatis-plus:

    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="globalConfig">
            <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
                <property name="dbConfig">
                    <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig">
                        <property name="idType" value="AUTO"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

4.3.2 tablePrefix

配置表名前缀,全局配置后可省略@TableName()配置。

如"tb_user"表,那么就可以配置前缀"tb_"。

springboot整合mybatis-plus,需要在application.properties中配置:

mybatis-plus.global-config.db-config.table-prefix=tb_

spring整合mybatis-plus:

    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="globalConfig">
            <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
                <property name="dbConfig">
                    <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig">
                        <property name="idType" value="AUTO"/>
                        <property name="tablePrefix" value="tb_" /> <!-- 只需要添加这一句,其他的都是别的配置 -->
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

5. 条件构造器

官方文档地址:https://mybatis.plus/guide/wrapper.html

在MybatisPlus中,Wrapper接口的实现类关系如下:

可以看到,AbstractWrapper和AbstractChainWrapper是重点实现,接下来我们重点学习AbstractWrapper以及其子类。

说明:

QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件。

注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为

5.1 allEq

allEq()方法如下:

allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)

参数说明:

  • params参数是一个Map集合,键是数据库中的字段名,值是条件值。
  • null2IsNull参数是一个布尔值,为true时则在Map的值为null时调用is null判断,为false时则忽略值为null的。

示例1:如果是allEq(params)方法,那么如果有字段为null,那么SQL语句就会按照is null处理。

    @Test
    public void testAllEq() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", 2);
        map.put("name", "李四");
        map.put("age", null);
        Wrapper<User> wrapper=new QueryWrapper<User>();
        ((QueryWrapper<User>) wrapper).allEq(map);
        List<User> userList = userMapper.selectList(wrapper);
        for (User user : userList) {
            System.out.println(user);
        }
    }

示例1:如果是allEq(params, null2IsNull)方法,那么如果有字段为null并且null2IsNull参数为false,那么SQL语句就会忽略值为null的字段。

    @Test
    public void testAllEq2() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", 2);
        map.put("name", "李四");
        map.put("age", null);
        Wrapper<User> wrapper = new QueryWrapper<User>();
        ((QueryWrapper<User>) wrapper).allEq(map, false);// 添加一个参数为false
        List<User> userList = userMapper.selectList(wrapper);
        for (User user : userList) {
            System.out.println(user);
        }
    }

allEq()方法还有下面这些重载方法:

allEq(BiPredicate<R, V> filter, Map<R, V> params)
allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)

参数说明:

  • filter参数是过滤函数,允许字段传入对比条件。
  • params参数同上。
  • null2IsNull参数同上。

示例:

    @Test
    public void testAllEq3() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", 2);
        map.put("name", "李四");
        map.put("age", null);
        Wrapper<User> wrapper = new QueryWrapper<User>();
        // 意思是Map中的键名存在"name"或"age"才进行查询
        ((QueryWrapper<User>) wrapper).allEq((k, v) -> (k.equals("name") || k.equals("age")), map, false);
        List<User> userList = userMapper.selectList(wrapper);
        for (User user : userList) {
            System.out.println(user);
        }
    }

5.2 基本比较操作

方法如下:

  • eq:等于(=)
  • ne:不等于(!=或<>)
  • gt:大于(>)
  • ge:大于等于(>=)
  • lt:小于(<)
  • le:小于等于(<=)
  • between:在某两个值范围之间(BETWEEN 值1 AND 值2)
  • notBetween:不在某两个值范围之间(NOT BETWEEN 值1 AND 值2)
  • in:字段在某些值中(IN (值1, 值2, 值3, ...))

示例:

    @Test
    public void testEq() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        /*
            等价于
                select * from tb_user where passowrd=? and age>=? and name in (?,?,?)
         */
        wrapper.eq("password", "123456")
                .ge("age", 15)
                .in("name", "张三", "李四", "王五");
        List<User> userList = userMapper.selectList(wrapper);
        for (User user : userList) {
            System.out.println(user);
        }
    }

5.3 模糊查询

模糊查询有的方法如下:

  • like:即等价于like '%关键字%'
    • 例如:like("name", "王") 等价于 name like '%王%'
  • notLike:即等价于not like '%关键字%'
    • 例如:notLike("name", "王") 等价于 name not like '%王%'
  • likeLeft:即等价于like '%关键字'
    • 例如:likeLeft("name", "王") 等价于 name like '%王'
  • likeRight:即等价于like '关键字%'
    • 例如:likeRight("name", "王") 等价于 name like '王%'

示例:

    @Test
    public void testLike() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        /*
            等价于
                select * from tb_user where name like ?
         */
        wrapper.like("name", "王");
        List<User> userList = userMapper.selectList(wrapper);
        for (User user : userList) {
            System.out.println(user);
        }
    }

5.4 排序

排序用的方法有:

  • orderBy:等价于order by 字段
    • 例如:orderBy(true, true, "id", "name") 等价于 order by id ASC, name ASC
  • orderByAsc:等价于order by 字段,字段,.. ASC
    • 例如:orderByAsc("id", "name") 等价于 order by id ASC, name ASC
  • orderByDesc:等价于order by 字段,字段,.. DESC
    • 例如:orderByDesc("id", "name") 等价于 order by id DESC, name DESC

示例:

    @Test
    public void testOrderBy() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        /*
            等价于
                select * from tb_user order by age desc
         */
        wrapper.orderByDesc("age");
        List<User> userList = userMapper.selectList(wrapper);
        for (User user : userList) {
            System.out.println(user);
        }
    }

5.5 逻辑查询

逻辑查询就是AND或OR,方法有:

  • OR:即等价于SQL语句拼接OR,主动调用OR表示紧接着下一个方法不是用AND连接(不调用OR则默认使用AND连接)
  • AND:即等价于SQL语句拼接AND。

示例:

    @Test
    public void testOr() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        /*
            等价于
                select * from tb_user where name=? or age=?
         */
        wrapper.eq("name", "李四").or().eq("age", 24);
        List<User> userList = userMapper.selectList(wrapper);
        for (User user : userList) {
            System.out.println(user);
        }
    }

5.6 select

在MybatisPlus查询中,默认是查询表中的所有字段,如果有需要可以通过select方法指定要查询的字段。示例:

    @Test
    public void testSelect() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        /*
            等价于
                select name,password from tb_user where name=? or age=?
         */
        wrapper.eq("name", "李四").or().eq("age", 24).select("name", "password");
        List<User> userList = userMapper.selectList(wrapper);
        for (User user : userList) {
            System.out.println(user);
        }
    }

6. ActiveRecord

ActiveRecord也属于ORM(对象关系映射)层,由Rails最早提出,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而且简洁易懂。

ActiveRecord的主要思想是:

  • 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录;通常表的每个字段在类中都有相应的Field;
  • ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD;;
  • ActiveRecord是一种领域模型(Domain Model),封装了部分业务逻辑

意思就是实例化一个实体类对象,就可以在该实例对象上执行增删改查的方法。

6.1 开启ActiveRecord

只需要让实体类继承Model<T>就可以了,其中T泛型是当前实体类。

例如:

@TableName("tb_user")
public class User extends Model<User> {// 继承extend Model<T>即可
    @TableId(value = "id", type = IdType.AUTO)// 设置id字段为自增长
    private Long id;
    private String username;
    private String password;
    private String name;
    private Integer age;
    private String email;
    // 无参和全参构造器、get和set方法、toString方法

6.2 根据id查询

直接在实体类对象上调用selectById()方法即可。

    @Test
    public void testAR1() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");// 加载配置文件是必要的
        // 实例化对象
        User user = new User();
        user.setId(4L);// 设置主键id
        // 调用AR的查询方法selectById()
        User resultUser = user.selectById();
        System.out.println(resultUser);
    }

注意:这里面的ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");代码是为了加载spring和mybatis配置文件,是必须的,但却不是AR使用必须的。

6.3 插入数据

插入数据在封装好实体类对象后,直接调用insert方法即可,返回一个布尔值表示是否插入成功。

    @Test
    public void testAR2() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        // 实例化对象,并封装要插入的数据
        User user = new User();
        user.setName("张飞");
        user.setAge(20);
        user.setPassword("abcdefg");
        user.setUsername("zhangfei");
        user.setEmail("zhangfei@qq.com");
        // 调用插入方法insert
        boolean result = user.insert();
        System.out.println("是否插入成功:" + result);
    }

6.4 更新数据

根据id进行更新,调用updateById方法即可。

    @Test
    public void testAR3() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        // 实例化对象,封装id和要更新的数据
        User user = new User();
        user.setId(3L);
        user.setPassword("xxxxxx");
        // 执行更新操作
        boolean result = user.updateById();
        System.out.println("是否更新成功:" + result);
    }

6.5 删除数据

删除数据根据id进行删除,调用deleteById方法。

    @Test
    public void testAR4() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        // 实例化对象,封装要删除的id
        User user = new User();
        user.setId(2L);
        // 执行删除操作
        boolean result = user.deleteById();
        System.out.println("是否删除成功:" + result);
    }

6.6 根据条件查询

根据条件查询就是设定QueryWrapper条件。

    @Test
    public void testAR5(){
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        // 实例化对象
        User user=new User();
        // 封装查询条件
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        wrapper.eq("username","zhangsan");
        // 进行查询
        List<User> userList = user.selectList(wrapper);
        for (User u : userList) {
            System.out.println(u);
        }
    }

7. 其他

7.1 SQL注入器

在MP中,通过AbstractSqlInjector将BaseMapper中的方法注入到了Mybatis容器,这样这些方法才可以正常执行。

我们如果要扩充BaseMapper接口中的方法,就可以使用SQL注入器来进行扩展方法。

下面以findById方法为例学习。

7.1.1 编写MyBaseMapper

定义一个接口MyBaseMapper<T>继承自mybatis-plus的接口BaseMapper<T>,并在里面写自己想要拓展的方法。

public interface MyBaseMapper<T> extends BaseMapper<T> {
    // 定义自己想要扩展的方法
    List<T> findAll();
}

然后其他的Mapper就可以继承我们自己写的MyBaseMapper<T>而不是继承BaseMapper<T>,这样就实现了统一的扩展。

// 继承自己写的MyBaseMapper<T>接口
public interface UserMapper extends MyBaseMapper<User> {
    
}

7.1.2 编写MySqlInjector

如果直接继承AbstractSqlInjector的话,原有的BaseMapper中的方法将失效,所以我们选择继承DefaultSqlInjector进行扩展。

public class MySqlInjector extends DefaultSqlInjector {// 继承DefaultSqlInjector类

    // 重写里面的getMethodList()方法
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        // 获取方法列表
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        // 在列表中添加自定义的方法
        methodList.add(new FindAll());
        // 最后返回列表
        return methodList;
    }
}

7.1.3 编写FindAll

然后写一个类FindAll(类名就是刚才自定义的方法名,首字母大写),继承AbstractMethod类。

public class FindAll extends AbstractMethod {// 继承AbstractMethod类

    // 并重写injectMappedStatement方法
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        // 定义的方法名
        String methodName = "findAll";
        // 拼接SQL语句
        String sql = "select * from " + tableInfo.getTableName();// 获取表名
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return addSelectMappedStatementForTable(mapperClass, methodName, sqlSource, tableInfo);
    }
}

7.1.4 注册到Spring容器

将自定义的ySqlInjector类注册到Spring的容器中。

如果是使用xml文件进行注册组件,需要在spring的核心配置文件applicationContext.xml添加配置:

<bean id="mySqlInjector" class="com.demo.extend.MySqlInjector"/>

如果是通过注解注册组件:

@Bean
public MySqlInjector mySqlInjector(){
    return new MySqlInjector();
}

7.1.5 进行测试

    @Test
    public void testFindById() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 调用自定义的方法findAll
        List<User> userList = userMapper.findAll();
        for (User user : userList) {
            System.out.println(user);
        }
    }

注意:我这里自定义并不能成功,请参考官网Demo

7.2 自动填充功能

所谓的自动填充就是在插入或更新数据的时候,某些字段自动填入我们想要的值,相当于设置默认值。

7.2.1 添加@TableField注解

只需要在需要自动填充的字段上添加@TableField注解即可。

FieldFill是一个枚举值,有多个模式可以选择:

public enum FieldFill {
    DEFAULT,// 默认不处理
    INSERT,// 插入时填充字段
    UPDATE,// 更新时填充字段
    INSERT_UPDATE;// 插入和更新时填充字段

    private FieldFill() {
    }
}

7.2.2  编写MyMetaObjectHandler

编写一个MyMetaObjectHandler类实现MetaObjectHandler接口,重写里面的insertFill方法和updateFill方法,如果要在插入时自动填充则重写insertFill方法,如果要在更新时自动填充则重写updateFill方法,如果既要在插入时自动填充又要在更新时自动填充则两个方法都重写。其中getFieldValByName()方法可以通过字段名来获取这个字段,来进行操作。setFieldValByName()方法可以设置某个字段的值。

@Component // 可以用该注解将该类Bean化
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        // 获取密码字段
        Object password = getFieldValByName("password", metaObject);
        // 判断密码字段是否为空,如果为空则进行自动填充,如果不为空则不进行自动填充
        if (null == password) {
            // 字段为空,进行填充
            setFieldValByName("password", "123456", metaObject);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {

    }
}

7.2.3  测试

    @Test
    public void testAutoInsert() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        User user = new User();
        user.setName("猪八戒");
        user.setUsername("zhubajie");
        user.setEmail("zhubajie@qq.com");
        user.setAge(1999);
        int result = userMapper.insert(user);
        System.out.println(result);
    }

注意:关于自动填充功能使用spring整合mybatis-plus失败,但是使用springboot整合mybatis-plus成功。

7.3 逻辑删除

7.3.1 修改表结构

所谓的逻辑删除就是不执行delete语句删除表中的记录,而是执行update语句修改记录的某个表示状态的属性(通常设定一个status字段,1表示已经逻辑删除,0表示未逻辑删除)

执行如下语句,为我们的测试表tb_user添加一个deleted字段,表示数据是否被删除,1表示被删除了,0表示未删除。

ALTER TABLE tb_user ADD COLUMN deleted int(1) null default 0;

同时修改User实体类,添加deleted属性并添加@TableLogic注解,表示这个字段可能要进行逻辑删除。

@TableLogic
private Integer deleted;

7.3.2 配置

如果是springboot则在application.properties文件中添加如下:

# 逻辑已删除值(默认为1)
mybatis-plus.global-config.db-config.logic-delete-value=1
# 逻辑未删除值(默认为0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0

如果是spring整合mybatis-plus,则在spring的核心配置文件applicationContext.xml中配置:

    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="globalConfig">
            <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
                <property name="dbConfig">
                    <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig">
                        <!-- 如下两句代码是配置的核心 -->
                        <property name="logicDeleteValue" value="1"/>
                        <property name="logicNotDeleteValue" value="0"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

 注意,这里的logicDeleteValue值为1是因为我在数据库表中规定1表示已经被逻辑删除了,logicNotDeleteValue值为0是因为我在数据库表中规定0表示未逻辑删除,这两个值你可以是1和-1,可以是任何你想标记的数字。

7.3.3 测试

执行deleteById方法进行逻辑删除。

    @Test
    public void testLogicDelete() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 执行逻辑删除
        int result = userMapper.deleteById(2L);
        System.out.println(result);
    }

7.4 通用枚举

枚举就是让一个字段的值只在某几个值中选择。比如性别只能是“男”或者“女”,不能是其他性别。

7.4.1 修改表结构

执行下面的SQL语句,为我们的tb_user表添加一个性别sex字段,但是我们不在表中直接存储“男”或“女”字符串,而是用数字1表示性别男,数字2表示性别女。

ALTER TABLE tb_user ADD COLUMN sex int(1) NULL DEFAULT 1 COMMENT '1-男, 2-女';

7.4.2 定义枚举

创建一个枚举类并实现IEnum<Integer>接口。

public enum SexEnum implements IEnum<Integer> {
    MAN(1, "男"),
    WOMAN(2, "女");

    private int value;
    private String desc;

    SexEnum(int value, String desc) {
        this.value = value;
        this.desc = desc;
    }

    @Override
    public Integer getValue() {
        return this.value;
    }

    @Override
    public String toString() {
        return this.desc;
    }
}

 7.4.3 配置

如果是springboot项目则在application.properties中添加枚举包扫描:

# 枚举包扫描
mybatis-plus.type-enums-package=com.demo.enum

如果是spring整合mybatis-plus项目则需要在applicationContext.xml中配置:

7.4.4 修改实体类

然后将枚举类型应用到实体类中

7.4.5 测试

测试插入数据用枚举类型。

    @Test
    public void testInsertByEnum() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 封装要插入的数据
        User user = new User();
        user.setName("关银屏");
        user.setUsername("guanyinping");
        user.setAge(35);
        user.setEmail("guanyinping@qq.com");
        user.setPassword("xxxxxx");
        user.setSex(SexEnum.WOMAN);// 设置性别用枚举类型
        // 执行插入
        int result = userMapper.insert(user);
        System.out.println(result);
    }

测试查询,它会自动映射为中文。

    @Test
    public void testSelectByEnum() {
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserMapper userMapper = (UserMapper) app.getBean("userMapper");
        // 执行查询
        List<User> userList = userMapper.selectList(null);
        for (User user : userList) {
            System.out.println(user);
        }
    }

本节源码参考:GitHub的Demo

  • 4
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值