当前位置:   article > 正文

Mybatis-Plus 详解_mybatisplus

mybatisplus

1. Mybatis-Plus概念

1.1 Mybatis-Plus介绍

官⽹: https://mybatis.plus/ https://mp.baomidou.com/
Mybatis-Plus 介绍
MyBatis-Plus (简称 MP )是⼀个 MyBatis 的增强⼯具,在 MyBatis 的基础上只做增强不做改变,-为简化开发、提⾼效率⽽⽣。

愿景
我们的愿景是成为 MyBatis 最好的搭档,就像 魂⽃罗 中的 1P 2P ,基友搭配,效率翻倍。

1.2 特性

  • ⽆侵⼊:只做增强不做改变,引⼊它不会对现有⼯程产⽣影响,如丝般顺滑
  • 损耗⼩:启动即会⾃动注⼊基本 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 查询
  • 分⻚插件⽀持多种数据库:⽀持 MySQLMariaDBOracleDB2H2HSQLSQLitePostgreSQLServer 等多种数据库
  • 内置性能分析插件:可输出 Sql 语句以及其执⾏时间,建议开发测试时启⽤该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete update 操作智能分析阻断,也可⾃定义拦截规则,预防误操作

1.3 架构

1.4 作者

Mybatis-Plus 是由 baomidou (苞⽶⾖)组织开发并且开源的,⽬前该组织⼤概有 30 ⼈左右。
码云地址: https://gitee.com/organizations/baomidou

2. Mybatis-Plus快速⼊⻔

2.1 安装

全新的 MyBatis-Plus 3.0 版本基于 JDK8 ,提供了 lambda 形式的调⽤,所以安装集成 MP3.0 要求
如下:
  • JDK 8+
  • Maven or Gradle
Release
Spring Boot
Maven
  1. <dependency>
  2. <groupId>com.baomidou</groupId>
  3. <artifactId>mybatis-plus-boot-starter</artifactId>
  4. <version>3.4.0</version>
  5. </dependency>
Spring MVC
Maven:
  1. <dependency>
  2. <groupId>com.baomidou</groupId>
  3. <artifactId>mybatis-plus</artifactId>
  4. <version>3.4.0</version>
  5. </dependency>
对于 Mybatis 整合 MP 有常常有三种⽤法,分别是 Mybatis+MP Spring+Mybatis+MP Spring
Boot+Mybatis+MP

2.2 创建数据库以及表

创建 User 表,其表结构如下:

  1. -- 创建测试表
  2. DROP TABLE IF EXISTS tb_user;
  3. CREATE TABLE user
  4. (
  5. id BIGINT(20) NOT NULL COMMENT '主键ID',
  6. name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
  7. age INT(11) NULL DEFAULT NULL COMMENT '年龄',
  8. email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
  9. PRIMARY KEY (id)
  10. );
  11. -- 插⼊测试数据
  12. INSERT INTO user (id, name, age, email) VALUES
  13. (1, 'Jone', 18, 'test1@baomidou.com'),
  14. (2, 'Jack', 20, 'test2@baomidou.com'),
  15. (3, 'Tom', 28, 'test3@baomidou.com'),
  16. (4, 'Sandy', 21, 'test4@baomidou.com'),
  17. (5, 'Billie', 24, 'test5@baomidou.com');

2.3 创建⼯程

 导⼊依赖:

  1. <dependencies>
  2. <!-- mybatis-plus插件依赖 -->
  3. <dependency>
  4. <groupId>com.baomidou</groupId>
  5. <artifactId>mybatis-plus</artifactId>
  6. <version>3.1.1</version>
  7. </dependency>
  8. <!--Mysql-->
  9. <dependency>
  10. <groupId>mysql</groupId>
  11. <artifactId>mysql-connector-java</artifactId>
  12. <version>5.1.47</version>
  13. </dependency>
  14. <!--连接池-->
  15. <dependency>
  16. <groupId>com.alibaba</groupId>
  17. <artifactId>druid</artifactId>
  18. <version>1.0.11</version>
  19. </dependency>
  20. <!--简化bean代码的⼯具包-->
  21. <dependency>
  22. <groupId>org.projectlombok</groupId>
  23. <artifactId>lombok</artifactId>
  24. <version>1.18.4</version>
  25. </dependency>
  26. <dependency>
  27. <groupId>junit</groupId>
  28. <artifactId>junit</artifactId>
  29. <version>4.12</version>
  30. </dependency>
  31. <dependency>
  32. <groupId>org.slf4j</groupId>
  33. <artifactId>slf4j-log4j12</artifactId>
  34. <version>1.6.4</version>
  35. </dependency>
  36. </dependencies>
  37. <build>
  38. <plugins>
  39. <plugin>
  40. <groupId>org.apache.maven.plugins</groupId>
  41. <artifactId>maven-compiler-plugin</artifactId>
  42. <configuration>
  43. <source>1.8</source>
  44. <target>1.8</target>
  45. </configuration>
  46. </plugin>
  47. </plugins>
  48. </build>

2.4 Mybatis + MP

下⾯演示,通过纯 Mybatis Mybatis-Plus 整合。
创建⼦ Module
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <parent>
  7. <artifactId>lagou-mybatis-plus</artifactId>
  8. <groupId>com.lagou.mp</groupId>
  9. <version>1.0-SNAPSHOT</version>
  10. </parent>
  11. <modelVersion>4.0.0</modelVersion>
  12. <artifactId>lagou-mybatis-plus-simple</artifactId>
  13. </project>
log4j.properties
  1. log4j.rootLogger=DEBUG,A1
  2. log4j.appender.A1=org.apache.log4j.ConsoleAppender
  3. log4j.appender.A1.layout=org.apache.log4j.PatternLayout
  4. log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
Mybatis 实现查询 User
第⼀步,编写 mybatis-config.xml ⽂件
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <properties resource="jdbc.properties"></properties>
  7. <!--environments: 运⾏环境-->
  8. <environments default="development">
  9. <environment id="development">
  10. <!--当前的事务事务管理器是JDBC-->
  11. <transactionManager type="JDBC"></transactionManager>
  12. <!--数据源信息 POOLED:使⽤mybatis的连接池-->
  13. <dataSource type="POOLED">
  14. <property name="driver" value="${jdbc.driver}"/>
  15. <property name="url" value="${jdbc.url}"/>
  16. <property name="username" value="${jdbc.username}"/>
  17. <property name="password" value="${jdbc.password}"/>
  18. </dataSource>
  19. </environment>
  20. </environments>
  21. <!--引⼊映射配置⽂件-->
  22. <mappers>
  23. <mapper resource="mapper/UserMapper.xml"></mapper>
  24. </mappers>
  25. </configuration>
第⼆步,编写 User 实体对象:(这⾥使⽤ lombok 进⾏了进化 bean 操作)
  1. @Data // getter setter @toString
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. public class User {
  5. private Long id;
  6. private String name;
  7. private Integer age;
  8. private String email; }
第三步,编写 UserMapper 接⼝:
  1. public interface UserMapper {
  2. List<User> findAll();
  3. }
第四步,编写 UserMapper.xml ⽂件:
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.lagou.mapper.UserMapper">
  6. <!-- 查询所有 -->
  7. <select id="findAll" resultType="com.lagou.pojo.User">
  8. select * from user
  9. </select>
  10. </mapper>
第五步,编写 TestMybatis 测试⽤例:
  1. public class MPTest {
  2. @Test
  3. public void test1() throws IOException {
  4. InputStream resourceAsStream =
  5. Resources.getResourceAsStream("sqlMapConfig.xml");
  6. SqlSessionFactory sqlSessionFactory = new
  7. SqlSessionFactoryBuilder().build(resourceAsStream);
  8. SqlSession sqlSession = sqlSessionFactory.openSession();
  9. UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  10. List<User> all = mapper.findAll();
  11. for (User user : all) {
  12. System.out.println(user);
  13. }
  14. }
  15. }
测试结果:
  1. User(id=1, name=Jone, age=18, email=test1@baomidou.com)
  2. User(id=2, name=Jack, age=20, email=test2@baomidou.com)
  3. User(id=3, name=Tom, age=28, email=test3@baomidou.com)
  4. User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
  5. User(id=5, name=Billie, age=24, email=test5@baomidou.com)
注:如果实体类名称和表名称不⼀致,可以在实体类上添加注解 @TableName(" 指定数据库表名 ")
Mybatis+MP 实现查询 User
第⼀步,将 UserMapper 继承 BaseMapper ,将拥有了 BaseMapper 中的所有⽅法:
  1. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  2. import com.lagou.pojo.User;
  3. public interface UserMapper extends BaseMapper<User> {
  4. }
第⼆步,使⽤ MP 中的 MybatisSqlSessionFactoryBuilder 进程构建:
  1. @Test
  2. public void test2() throws IOException {
  3. InputStream resourceAsStream =
  4. Resources.getResourceAsStream("sqlMapConfig.xml");
  5. //这⾥使⽤的是MP中的MybatisSqlSessionFactoryBuilder
  6. SqlSessionFactory sqlSessionFactory = new
  7. MybatisSqlSessionFactoryBuilder().build(resourceAsStream);
  8. SqlSession sqlSession = sqlSessionFactory.openSession();
  9. UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  10. // 可以调⽤BaseMapper中定义的⽅法
  11. List<User> all = mapper.selectList(null);
  12. for (User user : all) {
  13. System.out.println(user);
  14. }
  15. }
测试:
  1. User(id=1, name=Jone, age=18, email=test1@baomidou.com)
  2. User(id=2, name=Jack, age=20, email=test2@baomidou.com)
  3. User(id=3, name=Tom, age=28, email=test3@baomidou.com)
  4. User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
  5. User(id=5, name=Billie, age=24, email=test5@baomidou.com)
注:如果实体类名称和表名称不⼀致,可以在实体类上添加注解 @TableName(" 指定数据库表名 ")
简单说明:
  • 由于使⽤了 MybatisSqlSessionFactoryBuilder进⾏了构建,继承的BaseMapper中的⽅法就载⼊到了SqlSession中,所以就可以直接使⽤相关的⽅法;
  • 如图

2.5 Spring + Mybatis + MP

引⼊了 Spring 框架,数据源、构建等⼯作就交给了 Spring 管理。
创建⼦ Module
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <parent>
  7. <artifactId>lagou-mybatis-plus</artifactId>
  8. <groupId>com.lagou.mp</groupId>
  9. <version>1.0-SNAPSHOT</version>
  10. </parent>
  11. <modelVersion>4.0.0</modelVersion>
  12. <artifactId>lagou-mybatis-plus-spring</artifactId>
  13. <properties>
  14. <spring.version>5.1.6.RELEASE</spring.version>
  15. </properties>
  16. <dependencies>
  17. <dependency>
  18. <groupId>org.springframework</groupId>
  19. <artifactId>spring-webmvc</artifactId>
  20. <version>${spring.version}</version>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework</groupId>
  24. <artifactId>spring-jdbc</artifactId>
  25. <version>${spring.version}</version>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.springframework</groupId>
  29. <artifactId>spring-test</artifactId>
  30. <version>${spring.version}</version>
  31. </dependency>
  32. </dependencies>
实现查询 User
第⼀步,编写 jdbc.properties
  1. jdbc.driver=com.mysql.jdbc.Driver
  2. jdbc.url=jdbc:mysql://127.0.0.1:3306/mp?serverTimezone=GMT%2B8&useSSL=false
  3. jdbc.username=root
  4. jdbc.password=root
第⼆步,编写 applicationContext.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="
  6. http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/context
  9. http://www.springframework.org/schema/context/spring-context.xsd">
  10. <!--引⼊properties-->
  11. <context:property-placeholder location="classpath:jdbc.properties"/>
  12. <!--dataSource-->
  13. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
  14. <property name="driverClassName" value="${jdbc.driver}"/>
  15. <property name="url" value="${jdbc.url}"/>
  16. <property name="username" value="${jdbc.username}"/>
  17. <property name="password" value="${jdbc.password}"/>
  18. </bean>
  19. <!--这⾥使⽤MP提供的sqlSessionFactory,完成spring与mp的整合-->
  20. <bean id="sqlSessionFactory"
  21. class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"
  22. >
  23. <property name="dataSource" ref="dataSource"/>
  24. </bean>
  25. <!--扫描mapper接⼝,使⽤的依然是mybatis原⽣的扫描器-->
  26. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  27. <property name="basePackage" value="com.lagou.mapper"/>
  28. </bean>
  29. </beans>
第三步,编写 User 对象以及 UserMapper 接⼝:
  1. @Data
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. public class User {
  5. private Long id;
  6. private String name;
  7. private Integer age;
  8. private String email; }
  1. public interface UserMapper extends BaseMapper<User> {
  2. List<User> findAll();
  3. }
第四步,编写测试⽤例:
  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @ContextConfiguration(locations = "classpath:applicationContext.xml")
  3. public class TestSpringMP {
  4. @Autowired
  5. private UserMapper userMapper;
  6. @Test
  7. public void test2() throws IOException {
  8. List<User> users = this.userMapper.selectList(null);
  9. for (User user : users) {
  10. System.out.println(user);
  11. }
  12. }

2.6 SpringBoot + Mybatis + MP

使⽤ SpringBoot 将进⼀步的简化 MP 的整合,需要注意的是,由于使⽤ SpringBoot 需要继承 parent ,所以需要重新创建⼯程,并不是创建⼦Module
创建⼯程

导⼊依赖
  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter</artifactId>
  5. <exclusions>
  6. <exclusion>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-logging</artifactId>
  9. </exclusion>
  10. </exclusions>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-test</artifactId>
  15. <scope>test</scope>
  16. </dependency>
  17. <!--简化代码的⼯具包-->
  18. <dependency>
  19. <groupId>org.projectlombok</groupId>
  20. <artifactId>lombok</artifactId>
  21. <optional>true</optional>
  22. </dependency>
  23. <!--mybatis-plus的springboot⽀持-->
  24. <dependency>
  25. <groupId>com.baomidou</groupId>
  26. <artifactId>mybatis-plus-boot-starter</artifactId>
  27. <version>3.1.1</version>
  28. </dependency>
  29. <!--mysql驱动-->
  30. <dependency>
  31. <groupId>mysql</groupId>
  32. <artifactId>mysql-connector-java</artifactId>
  33. <version>5.1.47</version>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.slf4j</groupId>
  37. <artifactId>slf4j-log4j12</artifactId>
  38. </dependency>
  39. </dependencies>
  40. <build>
  41. <plugins>
  42. <plugin>
  43. <groupId>org.springframework.boot</groupId>
  44. <artifactId>spring-boot-maven-plugin</artifactId>
  45. </plugin>
  46. </plugins>
  47. </build>
log4j.properties
  1. log4j.rootLogger=DEBUG,A1
  2. log4j.appender.A1=org.apache.log4j.ConsoleAppender
  3. log4j.appender.A1.layout=org.apache.log4j.PatternLayout
  4. log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n

编写application.properties

  1. spring.datasource.driver-class-name=com.mysql.jdbc.Driver
  2. spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mp?
  3. useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=tr
  4. ue&useSSL=false
  5. spring.datasource.username=root
  6. spring.datasource.password=root

编写pojo

  1. @Data
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. public class User {
  5. private Long id;
  6. private String name;
  7. private Integer age;
  8. private String email;
  9. }
编写 mapper
  1. public interface UserMapper extends BaseMapper<User> {
  2. }
编写启动类
  1. package com.lagou.mp;
  2. import org.mybatis.spring.annotation.MapperScan;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.WebApplicationType;
  5. import org.springframework.boot.autoconfigure.SpringBootApplication;
  6. import org.springframework.boot.builder.SpringApplicationBuilder;
  7. @MapperScan("com.lagou.mp.mapper") //设置mapper接⼝的扫描包
  8. @SpringBootApplication
  9. public class MyApplication {
  10. public static void main(String[] args) {
  11. SpringApplication.run(MyApplication.class, args);
  12. }
  13. }

编写测试⽤例

  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9. import java.util.List;
  10. @RunWith(SpringRunner.class)
  11. @SpringBootTest
  12. public class UserMapperTest {
  13. @Autowired
  14. private UserMapper userMapper;
  15. @Test
  16. public void testSelect() {
  17. List<User> userList = userMapper.selectList(null);
  18. for (User user : userList) {
  19. System.out.println(user);
  20. }
  21. }
  22. }
测试:
  1. User(id=1, name=Jone, age=18, email=test1@baomidou.com)
  2. User(id=2, name=Jack, age=20, email=test2@baomidou.com)
  3. User(id=3, name=Tom, age=28, email=test3@baomidou.com)
  4. User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
  5. User(id=5, name=Billie, age=24, email=test5@baomidou.com)

3. 通⽤CRUD

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

3.1 插⼊操作

⽅法定义
  1. /**
  2. * 插⼊⼀条记录
  3. *
  4. * @param entity 实体对象.
  5. */
  6. int insert(T entity);
测试⽤例
  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class UserMapperTest {
  4. @Autowired
  5. private UserMapper userMapper;
  6. @Test
  7. public void testInsert(){
  8. User user = new User();
  9. user.setAge(18);
  10. user.setEmail("test@lagou.cn");
  11. user.setName("⼦慕");
  12. //返回的result是受影响的⾏数,并不是⾃增后的id
  13. int result = userMapper.insert(user);
  14. System.out.println(result);
  15. System.out.println(user.getId());
  16. }
  17. }
测试
1
1318744682116739074
可以看到,数据已经写⼊到了数据库,但是, id 的值不正确,我们期望的是数据库⾃增⻓,实际是 MP
成了 id 的值写⼊到了数据库。
如何设置 id 的⽣成策略呢?
MP ⽀持的 id 策略:
  1. package com.baomidou.mybatisplus.annotation;
  2. import lombok.Getter;
  3. /**
  4. * ⽣成ID类型枚举类
  5. *
  6. * @author hubin
  7. * @since 2015-11-10
  8. */
  9. @Getter
  10. public enum IdType {
  11. /**
  12. * 数据库ID⾃增
  13. */
  14. AUTO(0),
  15. /**
  16. * 该类型为未设置主键类型
  17. */
  18. NONE(1),
  19. /**
  20. * ⽤户输⼊ID
  21. * <p>该类型可以通过⾃⼰注册⾃动填充插件进⾏填充</p>
  22. */
  23. INPUT(2),
  24. /* 以下3种类型、只有当插⼊对象ID 为空,才⾃动填充。 */
  25. /**
  26. * 全局唯⼀ID (idWorker)
  27. */
  28. ID_WORKER(3),
  29. /**
  30. * 全局唯⼀ID (UUID)
  31. */
  32. UUID(4),
  33. /**
  34. * 字符串全局唯⼀ID (idWorker 的字符串表示)
  35. */
  36. ID_WORKER_STR(5);
  37. private final int key;
  38. IdType(int key) {
  39. this.key = key;
  40. }
  41. }

修改 User 对象:
  1. package com.lagou.mp.pojo;
  2. import com.baomidou.mybatisplus.annotation.IdType;
  3. import com.baomidou.mybatisplus.annotation.TableId;
  4. import com.baomidou.mybatisplus.annotation.TableName;
  5. import lombok.AllArgsConstructor;
  6. import lombok.Data;
  7. import lombok.NoArgsConstructor;
  8. @Data
  9. @NoArgsConstructor
  10. @AllArgsConstructor
  11. @TableName("tb_user")
  12. public class User {
  13. @TableId(type = IdType.AUTO) //指定id类型为⾃增⻓
  14. private Long id;
  15. private String userName;
  16. private String password;
  17. private String name;
  18. private Integer age;
  19. private String email;
  20. }
数据插⼊成功:

@TableField
MP 中通过 @TableField 注解可以指定字段的⼀些属性,常常解决的问题有 2 个:
1 、对象中的属性名和字段名不⼀致的问题(⾮驼峰)
2 、对象中的属性字段在表中不存在的问题
使⽤:

 其他⽤法,如⼤字段不加⼊查询字段:

 效果:

3.2 更新操作

MP 中,更新操作有 2 种,⼀种是根据 id 更新,另⼀种是根据条件更新。
根据 id 更新
⽅法定义:
  1. /**
  2. * 根据 ID 修改
  3. *
  4. * @param entity 实体对象
  5. */
  6. int updateById(@Param(Constants.ENTITY) T entity);
测试:
  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class UserMapperTest {
  4. @Autowired
  5. private UserMapper userMapper;
  6. @Test
  7. public void testUpdateById() {
  8. User user = new User();
  9. user.setId(6L); //主键
  10. user.setAge(21); //更新的字段
  11. //根据id更新,更新不为null的字段
  12. this.userMapper.updateById(user);
  13. }
  14. }
结果:

根据条件更新
⽅法定义:
  1. /**
  2. * 根据 whereEntity 条件,更新记录
  3. *
  4. * @param entity 实体对象 (set 条件值,可以为 null)
  5. * @param updateWrapper 实体对象封装操作类(可以为 null,⾥⾯的 entity ⽤于⽣成
  6. where 语句)
  7. */
  8. int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER)
  9. Wrapper<T> updateWrapper);
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import com.baomidou.mybatisplus.core.conditions.Wrapper;
  5. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  6. import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  7. import net.minidev.json.writer.UpdaterMapper;
  8. import org.junit.Test;
  9. import org.junit.runner.RunWith;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.boot.test.context.SpringBootTest;
  12. import org.springframework.test.context.junit4.SpringRunner;
  13. import java.util.List;
  14. @RunWith(SpringRunner.class)
  15. @SpringBootTest
  16. public class UserMapperTest {
  17. @Autowired
  18. private UserMapper userMapper;
  19. @Test
  20. public void testUpdate() {
  21. User user = new User();
  22. user.setAge(22); //更新的字段
  23. //更新的条件
  24. QueryWrapper<User> wrapper = new QueryWrapper<>();
  25. wrapper.eq("id", 6);
  26. //执⾏更新操作
  27. int result = this.userMapper.update(user, wrapper);
  28. System.out.println("result = " + result);
  29. }
  30. }
或者,通过 UpdateWrapper 进⾏更新:
  1. @Test
  2. public void testUpdate() {
  3. //更新的条件以及字段
  4. UpdateWrapper<User> wrapper = new UpdateWrapper<>();
  5. wrapper.eq("id", 6).set("age", 23);
  6. //执⾏更新操作
  7. int result = this.userMapper.update(null, wrapper);
  8. System.out.println("result = " + result);
  9. }
测试结果:
[main] [com.lagou.mp.mapper.UserMapper.update]-[DEBUG] == > Preparing: UPDATE
tb_user SET age = ? WHERE id = ?
[main] [com.lagou.mp.mapper.UserMapper.update]-[DEBUG] == > Parameters:
23 (Integer), 6 (Integer)
[main] [com.lagou.mp.mapper.UserMapper.update]-[DEBUG] < == Updates: 1
均可达到更新的效果。
关于 wrapper 更多的⽤法后⾯会详细讲解。

3.3 删除操作

deleteById
⽅法定义:
  1. /**
  2. * 根据 ID 删除
  3. *
  4. * @param id 主键ID
  5. */
  6. int deleteById(Serializable id);
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import org.springframework.test.context.junit4.SpringRunner;
  8. @RunWith(SpringRunner.class)
  9. @SpringBootTest
  10. public class UserMapperTest {
  11. @Autowired
  12. private UserMapper userMapper;
  13. @Test
  14. public void testDeleteById() {
  15. //执⾏删除操作
  16. int result = this.userMapper.deleteById(6L);
  17. System.out.println("result = " + result);
  18. }
  19. }

结果:

[main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] == > Preparing:
DELETE FROM tb_user WHERE id = ?
[main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] == > Parameters:
6 (Long)
[main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] < == Updates: 1
数据被删除。
deleteByMap
⽅法定义:
  1. /**
  2. * 根据 columnMap 条件,删除记录
  3. *
  4. * @param columnMap 表字段 map 对象
  5. */
  6. int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object>
  7. columnMap);
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import org.springframework.test.context.junit4.SpringRunner;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10. @RunWith(SpringRunner.class)
  11. @SpringBootTest
  12. public class UserMapperTest {
  13. @Autowired
  14. private UserMapper userMapper;
  15. @Test
  16. public void testDeleteByMap() {
  17. Map<String, Object> columnMap = new HashMap<>();
  18. columnMap.put("age",21);
  19. columnMap.put("name","⼦慕");
  20. //将columnMap中的元素设置为删除的条件,多个之间为and关系
  21. int result = this.userMapper.deleteByMap(columnMap);
  22. System.out.println("result = " + result);
  23. }
  24. }

结果:

[main] [com.lagou.mp.mapper.UserMapper.deleteByMap]-[DEBUG] == > Preparing:
DELETE FROM tb_user WHERE name = ? AND age = ?
[main] [com.lagou.mp.mapper.UserMapper.deleteByMap]-[DEBUG] == > Parameters:
(String), 21 (Integer)
[main] [com.lagou.mp.mapper.UserMapper.deleteByMap]-[DEBUG] < == Updates: 0
delete
⽅法定义:
  1. /**
  2. * 根据 entity 条件,删除记录
  3. *
  4. * @param wrapper 实体对象封装操作类(可以为 null)
  5. */
  6. int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import org.junit.Test;
  6. 结果:
  7. 3.3.4、deleteBatchIds
  8. ⽅法定义:
  9. import org.junit.runner.RunWith;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.boot.test.context.SpringBootTest;
  12. import org.springframework.test.context.junit4.SpringRunner;
  13. import java.util.HashMap;
  14. import java.util.Map;
  15. @RunWith(SpringRunner.class)
  16. @SpringBootTest
  17. public class UserMapperTest {
  18. @Autowired
  19. private UserMapper userMapper;
  20. @Test
  21. public void testDeleteByMap() {
  22. User user = new User();
  23. user.setAge(20);
  24. user.setName("⼦慕");
  25. //将实体对象进⾏包装,包装为操作条件
  26. QueryWrapper<User> wrapper = new QueryWrapper<>(user);
  27. int result = this.userMapper.delete(wrapper);
  28. System.out.println("result = " + result);
  29. }
  30. }

结果:

[main] [com.lagou.mp.mapper.UserMapper.delete]-[DEBUG] == > Preparing: DELETE
FROM tb_user WHERE name = ? AND age = ?
[main] [com.lagou.mp.mapper.UserMapper.delete]-[DEBUG] == > Parameters: ⼦慕
(String), 20 (Integer)
[main] [com.lagou.mp.mapper.UserMapper.delete]-[DEBUG] < == Updates: 0

3.3.4deleteBatchIds

⽅法定义:
  1. /**
  2. * 删除(根据ID 批量删除)
  3. *
  4. * @param idList 主键ID列表(不能为 null 以及 empty)
  5. */
  6. int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends
  7. Serializable> idList);
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import org.springframework.test.context.junit4.SpringRunner;
  8. import java.util.Arrays;
  9. @RunWith(SpringRunner.class)
  10. @SpringBootTest
  11. public class UserMapperTest {
  12. @Autowired
  13. private UserMapper userMapper;
  14. @Test
  15. public void testDeleteByMap() {
  16. //根据id集合批量删除
  17. int result =
  18. this.userMapper.deleteBatchIds(Arrays.asList(1L,10L,20L));
  19. System.out.println("result = " + result);
  20. }
  21. }
结果:
[main] [com.lagou.mp.mapper.UserMapper.deleteBatchIds]-[DEBUG] == > Preparing:
DELETE FROM tb_user WHERE id IN ( ? , ? , ? )
[main] [com.lagou.mp.mapper.UserMapper.deleteBatchIds]-[DEBUG] == > Parameters:
1 (Long), 10 (Long), 20 (Long)
[main] [com.lagou.mp.mapper.UserMapper.deleteBatchIds]-[DEBUG] < == Updates:
1

3.4 查询操作

MP 提供了多种查询操作,包括根据 id 查询、批量查询、查询单条数据、查询列表、分⻚查询等操作。

3.4.1selectById

⽅法定义:
  1. /**
  2. * 根据 ID 查询
  3. *
  4. * @param id 主键ID
  5. */
  6. T selectById(Serializable id);
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9. @RunWith(SpringRunner.class)
  10. @SpringBootTest
  11. public class UserMapperTest {
  12. @Autowired
  13. private UserMapper userMapper;
  14. @Test
  15. public void testSelectById() {
  16. //根据id查询数据
  17. User user = this.userMapper.selectById(2L);
  18. System.out.println("result = " + user);
  19. }
  20. }
结果:
result = User (id = 2 , name = Jack, age = 20 , email = test2@baomidou.com)

3.4.2selectBatchIds

⽅法定义:
  1. /**
  2. * 查询(根据ID 批量查询)
  3. *
  4. * @param idList 主键ID列表(不能为 null 以及 empty)
  5. */
  6. List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends
  7. Serializable> idList);
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9. import java.util.Arrays;
  10. import java.util.List;
  11. @RunWith(SpringRunner.class)
  12. @SpringBootTest
  13. public class UserMapperTest {
  14. @Autowired
  15. private UserMapper userMapper;
  16. @Test
  17. public void testSelectBatchIds() {
  18. //根据id集合批量查询
  19. List<User> users = this.userMapper.selectBatchIds(Arrays.asList(2L,
  20. 3L, 10L));
  21. for (User user : users) {
  22. System.out.println(user);
  23. }
  24. }
  25. }
结果:
User (id = 2 , name = Jack, age = 20 , email = test2@baomidou.com)
User (id = 3 , name = Tom, age = 28 , email = test3@baomidou.com)

3.4.3selectOne

⽅法定义:
  1. /**
  2. * 根据 entity 条件,查询⼀条记录
  3. *
  4. * @param queryWrapper 实体对象封装操作类(可以为 null)
  5. */
  6. T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. @RunWith(SpringRunner.class)
  11. @SpringBootTest
  12. public class UserMapperTest {
  13. @Autowired
  14. private UserMapper userMapper;
  15. @Test
  16. public void testSelectOne() {
  17. QueryWrapper<User> wrapper = new QueryWrapper<User>();
  18. wrapper.eq("name", "jack");
  19. //根据条件查询⼀条数据,如果结果超过⼀条会报错
  20. User user = this.userMapper.selectOne(wrapper);
  21. System.out.println(user);
  22. }
  23. }
结果:
User (id = 2 , name = Jack, age = 20 , email = test2@baomidou.com)

3.4.4selectCount

⽅法定义:
  1. /**
  2. * 根据 Wrapper 条件,查询总记录数
  3. *
  4. * @param queryWrapper 实体对象封装操作类(可以为 null)
  5. */
  6. Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. @RunWith(SpringRunner.class)
  11. @SpringBootTest
  12. public class UserMapperTest {
  13. @Autowired
  14. private UserMapper userMapper;
  15. @Test
  16. public void testSelectCount() {
  17. QueryWrapper<User> wrapper = new QueryWrapper<User>();
  18. wrapper.gt("age", 23); //年龄⼤于23岁
  19. //根据条件查询数据条数
  20. Integer count = this.userMapper.selectCount(wrapper);
  21. System.out.println("count = " + count);
  22. }
  23. }
结果:
count = 2

3.4.5selectList

⽅法定义:
  1. /**
  2. * 根据 entity 条件,查询全部记录
  3. *
  4. * @param queryWrapper 实体对象封装操作类(可以为 null)
  5. */
  6. List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. import java.util.List;
  11. @RunWith(SpringRunner.class)
  12. @SpringBootTest
  13. public class UserMapperTest {
  14. @Autowired
  15. private UserMapper userMapper;
  16. @Test
  17. public void testSelectList() {
  18. QueryWrapper<User> wrapper = new QueryWrapper<User>();
  19. wrapper.gt("age", 23); //年龄⼤于23岁
  20. //根据条件查询数据
  21. List<User> users = this.userMapper.selectList(wrapper);
  22. for (User user : users) {
  23. System.out.println("user = " + user);
  24. }
  25. }
  26. }
结果:
user = User (id = 3 , name = Tom, age = 28 , email = test3@baomidou.com)
user = User (id = 5 , name = Billie, age = 24 , email = test5@baomidou.com)

3.4.6selectPage

⽅法定义:
  1. /**
  2. * 根据 entity 条件,查询全部记录(并翻⻚)
  3. *
  4. * @param page 分⻚查询条件(可以为 RowBounds.DEFAULT)
  5. * @param queryWrapper 实体对象封装操作类(可以为 null)
  6. */
  7. IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T>
  8. queryWrapper);
配置分⻚插件:
  1. package com.lagou.mp;
  2. import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
  3. import org.mybatis.spring.annotation.MapperScan;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. @Configuration
  7. @MapperScan("com.lagou.mp.mapper") //设置mapper接⼝的扫描包
  8. public class MybatisPlusConfig {
  9. /**
  10. * 分⻚插件
  11. */
  12. @Bean
  13. public PaginationInterceptor paginationInterceptor() {
  14. return new PaginationInterceptor();
  15. }
  16. }
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import com.baomidou.mybatisplus.core.metadata.IPage;
  6. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  7. import org.junit.Test;
  8. import org.junit.runner.RunWith;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.boot.test.context.SpringBootTest;
  11. import org.springframework.test.context.junit4.SpringRunner;
  12. import java.util.List;
  13. @RunWith(SpringRunner.class)
  14. @SpringBootTest
  15. public class UserMapperTest {
  16. @Autowired
  17. private UserMapper userMapper;
  18. @Test
  19. public void testSelectPage() {
  20. QueryWrapper<User> wrapper = new QueryWrapper<User>();
  21. wrapper.gt("age", 20); //年龄⼤于20岁
  22. Page<User> page = new Page<>(1,1);
  23. //根据条件查询数据
  24. IPage<User> iPage = this.userMapper.selectPage(page, wrapper);
  25. System.out.println("数据总条数:" + iPage.getTotal());
  26. System.out.println("总⻚数:" + iPage.getPages());
  27. List<User> users = iPage.getRecords();
  28. for (User user : users) {
  29. System.out.println("user = " + user);
  30. }
  31. }
  32. }

结果:

数据总条数: 4
总⻚数: 4
user = User (id = 3 , name = Tom, age = 28 , email = test3@baomidou.com)

3.5 SQL注⼊的原理

前⾯我们已经知道, MP 在启动后会将 BaseMapper 中的⼀系列的⽅法注册到 meppedStatements 中, 那么究竟是如何注⼊的呢?流程⼜是怎么样的?下⾯我们将⼀起来分析下。
MP 中, ISqlInjector 负责 SQL 的注⼊⼯作,它是⼀个接⼝, AbstractSqlInjector 是它的实现类,实现关系如下:

AbstractSqlInjector 中,主要是由 inspectInject() ⽅法进⾏注⼊的,如下:
  1. @Override
  2. public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?>
  3. mapperClass) {
  4. Class<?> modelClass = extractModelClass(mapperClass);
  5. if (modelClass != null) {
  6. String className = mapperClass.toString();
  7. Set<String> mapperRegistryCache =
  8. GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration());
  9. if (!mapperRegistryCache.contains(className)) {
  10. List<AbstractMethod> methodList = this.getMethodList();
  11. if (CollectionUtils.isNotEmpty(methodList)) {
  12. TableInfo tableInfo =
  13. TableInfoHelper.initTableInfo(builderAssistant, modelClass);
  14. // 循环注⼊⾃定义⽅法
  15. methodList.forEach(m -> m.inject(builderAssistant,
  16. mapperClass, modelClass, tableInfo));
  17. } else {
  18. logger.debug(mapperClass.toString() + ", No effective
  19. injection method was found.");
  20. }
  21. mapperRegistryCache.add(className);
  22. }
  23. }
  24. }
在实现⽅法中, methodList.forEach(m -> m.inject(builderAssistant, mapperClass,
modelClass, tableInfo)); 是关键,循环遍历⽅法,进⾏注⼊。
最终调⽤抽象⽅法 injectMappedStatement 进⾏真正的注⼊:
  1. /**
  2. * 注⼊⾃定义 MappedStatement
  3. *
  4. * @param mapperClass mapper 接⼝
  5. * @param modelClass mapper 泛型
  6. * @param tableInfo 数据库表反射信息
  7. * @return MappedStatement
  8. */
  9. public abstract MappedStatement injectMappedStatement(Class<?>
  10. mapperClass, Class<?> modelClass, TableInfo tableInfo);
查看该⽅法的实现:

SelectById 为例查看:
  1. public class SelectById extends AbstractMethod {
  2. @Override
  3. public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?
  4. > modelClass, TableInfo tableInfo) {
  5. SqlMethod sqlMethod = SqlMethod.LOGIC_SELECT_BY_ID;
  6. SqlSource sqlSource = new RawSqlSource(configuration,
  7. String.format(sqlMethod.getSql(),
  8. sqlSelectColumns(tableInfo, false),
  9. tableInfo.getTableName(), tableInfo.getKeyColumn(),
  10. tableInfo.getKeyProperty(),
  11. tableInfo.getLogicDeleteSql(true, false)), Object.class);
  12. return this.addSelectMappedStatement(mapperClass,
  13. sqlMethod.getMethod(), sqlSource, modelClass, tableInfo);
  14. }
  15. }
可以看到,⽣成了 SqlSource 对象,再将 SQL 通过 addSelectMappedStatement ⽅法添加到meppedStatements中。

4. 配置

MP 中有⼤量的配置,其中有⼀部分是 Mybatis 原⽣的配置,另⼀部分是 MP 的配置,详情: https://m
ybatis.plus/config/
下⾯我们对常⽤的配置做讲解。

4.1、基本配置

4.1.1configLocation

MyBatis 配置⽂件位置,如果有单独的 MyBatis 配置,请将其路径配置到 configLocation 中。
MyBatis Configuration 的具体内容请参考 MyBatis 官⽅⽂档
Spring Boot
mybatis-plus.config-location = classpath:mybatis-config.xml

Spring MVC

  1. <bean id="sqlSessionFactory"
  2. class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"
  3. >
  4. <property name="configLocation" value="classpath:mybatis-config.xml"/>
  5. </bean>

4.1.2mapperLocations

MyBatis Mapper 所对应的 XML ⽂件位置,如果您在 Mapper 中有⾃定义⽅法( XML 中有⾃定义实现),需要进⾏该配置,告诉 Mapper 所对应的 XML ⽂件位置。
Spring Boot
mybatis-plus.mapper-locations = classpath*:mybatis/*.xml
Spring MVC
  1. <bean id="sqlSessionFactory"
  2. class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"
  3. >
  4. <property name="mapperLocations" value="classpath*:mybatis/*.xml"/>
  5. </bean>
Maven 多模块项⽬的扫描路径需以 classpath*: 开头 (即加载多个 jar 包下的 XML ⽂件)
测试:
UserMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.lagou.mp.mapper.UserMapper">
  6. <select id="findById" resultType="com.lagou.mp.pojo.User">
  7. select * from tb_user where id = #{id}
  8. </select>
  9. </mapper>
  1. package com.lagou.mp.mapper;
  2. import com.lagou.mp.pojo.User;
  3. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4. public interface UserMapper extends BaseMapper<User> {
  5. User findById(Long id);
  6. }
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9. @RunWith(SpringRunner.class)
  10. @SpringBootTest
  11. public class UserMapperTest {
  12. @Autowired
  13. private UserMapper userMapper;
  14. @Test
  15. public void testSelectPage() {
  16. User user = this.userMapper.findById(2L);
  17. System.out.println(user);
  18. }
  19. }
运⾏结果:

4.1.3typeAliasesPackage  

MyBaits 别名包扫描路径,通过该属性可以给包中的类注册别名,注册后在 Mapper 对应的 XML ⽂件中可以直接使⽤类名,⽽不⽤使⽤全限定的类名(即 XML 中调⽤的时候不⽤包含包名)。
Spring Boot
mybatis-plus.type-aliases-package = com.lagou.mp.pojo
Spring MVC
  1. <bean id="sqlSessionFactory"
  2. class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"
  3. >
  4. <property name="typeAliasesPackage"
  5. value="com.baomidou.mybatisplus.samples.quickstart.entity"/>
  6. </bean>

4.2、进阶配置

本部分( Configuration )的配置⼤都为 MyBatis 原⽣⽀持的配置,这意味着您可以通过 MyBatis XML配置⽂件的形式进⾏配置。

4.2.1mapUnderscoreToCamelCase

  • 类型: boolean
  • 默认值: true
是否开启⾃动驼峰命名规则( camel case )映射,即从经典数据库列名 A_COLUMN (下划线命名) 到经典 Java 属性名 aColumn (驼峰命名) 的类似映射。
注意:
此属性在 MyBatis 中原默认值为 false ,在 MyBatis-Plus 中,此属性也将⽤于⽣成最终的 SQL 的select body
如果您的数据库命名符合规则⽆需使⽤ @TableField 注解指定数据库字段名
示例( SpringBoot ):
 
  1. #关闭⾃动驼峰映射,该参数不能和mybatis-plus.config-location同时存在
  2. mybatis-plus.configuration.map-underscore-to-camel-case=false

4.2.2cacheEnabled

  • 类型: boolean
  • 默认值: true
全局地开启或关闭配置⽂件中的所有映射器已经配置的任何缓存,默认为 true
示例:
mybatis-plus.configuration.cache-enabled=false

4.3DB 策略配置

4.3.1idType

  • 类型: com.baomidou.mybatisplus.annotation.IdType
  • 默认值: ID_WORKER
全局默认主键类型,设置后,即可省略实体对象中的 @TableId(type = IdType.AUTO) 配置。
示例:
SpringBoot
mybatis-plus.global-config.db-config.id-type=auto
SpringMVC
  1. <!--这⾥使⽤MP提供的sqlSessionFactory,完成了Spring与MP的整合-->
  2. <bean id="sqlSessionFactory"
  3. class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"
  4. >
  5. <property name="dataSource" ref="dataSource"/>
  6. <property name="globalConfig">
  7. <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
  8. <property name="dbConfig">
  9. <bean
  10. class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
  11. <property name="idType" value="AUTO"/>
  12. </bean>
  13. </property>
  14. </bean>
  15. </property>
  16. </bean>

4.3.2tablePrefix

  • 类型: String
  • 默认值: null
表名前缀,全局配置后可省略 @TableName() 配置。
SpringBoot
mybatis-plus.global-config.db-config.table-prefix=tb_
SpringMVC
  1. <bean id="sqlSessionFactory"
  2. class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"
  3. >
  4. <property name="dataSource" ref="dataSource"/>
  5. <property name="globalConfig">
  6. <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
  7. <property name="dbConfig">
  8. <bean
  9. class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
  10. <property name="idType" value="AUTO"/>
  11. <property name="tablePrefix" value="tb_"/>
  12. </bean>
  13. </property>
  14. </bean>
  15. </property>
  16. </bean>

5. 条件构造器

MP 中, Wrapper 接⼝的实现类关系如下:

可以看到, AbstractWrapper AbstractChainWrapper 是重点实现,接下来我们重点学习
AbstractWrapper 以及其⼦类。
说明 :
QueryWrapper(LambdaQueryWrapper) UpdateWrapper(LambdaUpdateWrapper) 的⽗类
⽤于⽣成 sql where 条件 , entity 属性也⽤于⽣成 sql where 条件
注意 : entity ⽣成的 where 条件与 使⽤各个 api ⽣成的 where 条件 没有任何关联⾏为
官⽹⽂档地址: https://mybatis.plus/guide/wrapper.html

5.1allEq

5.1.1、说明

  1. allEq(Map<R, V> params)
  2. allEq(Map<R, V> params, boolean null2IsNull)
  3. allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
  • 全部eq(或个别isNull)
个别参数说明 :
params : key 为数据库字段名 , value 为字段值
null2IsNull : true 则在 map value null 时调⽤ isNull ⽅法 , false 时则忽
value null
1: allEq({id:1,name:" ⽼王 ",age:null}) ---> id = 1 and name = ' ⽼王 ' and age
is null
2: allEq({id:1,name:" ⽼王 ",age:null}, false) ---> id = 1 and name = ' ⽼王 '
  1. allEq(BiPredicate<R, V> filter, Map<R, V> params)
  2. allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
  3. allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean
  4. null2IsNull)
个别参数说明 :
filter : 过滤函数 , 是否允许字段传⼊⽐对条件中
params null2IsNull : 同上
1: allEq((k,v) -> k.indexOf("a") > 0, {id:1,name:" ⽼王 ",age:null}) ---
> name = ' ⽼王 ' and age is null
2: allEq((k,v) -> k.indexOf("a") > 0, {id:1,name:" ⽼王 ",age:null},
false) ---> name = ' ⽼王 '

5.1.2、测试⽤例

  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. import java.util.HashMap;
  11. import java.util.List;
  12. import java.util.Map;
  13. @RunWith(SpringRunner.class)
  14. @SpringBootTest
  15. public class UserMapperTest {
  16. @Autowired
  17. private UserMapper userMapper;
  18. @Test
  19. public void testWrapper() {
  20. QueryWrapper<User> wrapper = new QueryWrapper<>();
  21. //设置条件
  22. Map<String,Object> params = new HashMap<>();
  23. params.put("name", "jack");
  24. params.put("age", "20");
  25. // wrapper.allEq(params);//SELECT * FROM tb_user WHERE password IS NULL
  26. AND name = ? AND age = ?
  27. // wrapper.allEq(params,false); //SELECT * FROM tb_user WHERE name = ?
  28. AND age = ?
  29. // wrapper.allEq((k, v) -> (k.equals("name") || k.equals("age"))
  30. ,params);//SELECT * FROM tb_user WHERE name = ? AND age = ?
  31. List<User> users = this.userMapper.selectList(wrapper);
  32. for (User user : users) {
  33. System.out.println(user);
  34. }
  35. }
  36. }

5.2、基本⽐较操作

  • eq
    • 等于 =
  • ne
    • 不等于 <>
  • gt
    • ⼤于 >
  • ge
    • ⼤于等于 >=
  • lt
    • ⼩于 <
  • le
    • ⼩于等于 <=
  • between
    • BETWEEN 1 AND 2
  • notBetween
    • NOT BETWEEN 1 AND 2
  • in
    • 字段 IN (value.get(0), value.get(1), ...)
  • notIn
    • 字段 NOT IN (v0, v1, ...)
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. import java.util.List;
  11. @RunWith(SpringRunner.class)
  12. @SpringBootTest
  13. public class UserMapperTest {
  14. @Autowired
  15. private UserMapper userMapper;
  16. QueryWrapper<User> wrapper = new QueryWrapper<>();
  17. //SELECT id,name,age,email FROM tb_user WHERE password = ? AND age >=
  18. ? AND name IN (?,?,?)
  19. wrapper.eq("email", "test2@baomidou.com")
  20. .ge("age", 20)
  21. .in("name", "jack", "jone", "tom");
  22. List<User> users = this.userMapper.selectList(wrapper);
  23. for (User user : users) {
  24. System.out.println(user);
  25. }
  26. }
  27. }

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 '%'
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. import java.util.List;
  11. @RunWith(SpringRunner.class)
  12. @SpringBootTest
  13. public class UserMapperTest {
  14. @Autowired
  15. private UserMapper userMapper;
  16. @Test
  17. public void testWrapper() {
  18. QueryWrapper<User> wrapper = new QueryWrapper<>();
  19. //SELECT id,user_name,password,name,age,email FROM tb_user WHERE name
  20. LIKE ?
  21. //Parameters: %⼦%(String)
  22. wrapper.like("name", "⼦");
  23. List<User> users = this.userMapper.selectList(wrapper);
  24. for (User user : users) {
  25. System.out.println(user);
  26. }
  27. }
  28. }

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
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. import java.util.List;
  11. @RunWith(SpringRunner.class)
  12. @SpringBootTest
  13. public class UserMapperTest {
  14. @Autowired
  15. private UserMapper userMapper;
  16. @Test
  17. public void testWrapper() {
  18. QueryWrapper<User> wrapper = new QueryWrapper<>();
  19. //SELECT id,user_name,password,name,age,email FROM tb_user ORDER BY
  20. age DESC
  21. wrapper.orderByDesc("age");
  22. List<User> users = this.userMapper.selectList(wrapper);
  23. for (User user : users) {
  24. System.out.println(user);
  25. }
  26. }
  27. }

5.5、逻辑查询

  • or
    • 拼接 OR
    • 主动调⽤ or 表示紧接着下⼀个⽅法不是⽤ and 连接!(不调⽤ or 则默认为使⽤ and 连接)
  • and
    • AND 嵌套
    • : and(i -> i.eq("name", "李⽩").ne("status", "活着")) ---> and (name = '' and status <> '活着')
测试⽤例:
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. import java.util.List;
  11. @RunWith(SpringRunner.class)
  12. @SpringBootTest
  13. public class UserMapperTest {
  14. @Autowired
  15. private UserMapper userMapper;
  16. @Test
  17. public void testWrapper() {
  18. QueryWrapper<User> wrapper = new QueryWrapper<>();
  19. //SELECT id,user_name,password,name,age,email FROM tb_user WHERE name= ? OR age = ?
  20. wrapper.eq("name","jack").or().eq("age", 24);
  21. List<User> users = this.userMapper.selectList(wrapper);
  22. for (User user : users) {
  23. System.out.println(user);
  24. }
  25. }
  26. }

5.6select

MP 查询中,默认查询所有的字段,如果有需要也可以通过 select ⽅法进⾏指定字段。
  1. package com.lagou.mp;
  2. import com.lagou.mp.mapper.UserMapper;
  3. import com.lagou.mp.pojo.User;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. import java.util.List;
  11. @RunWith(SpringRunner.class)
  12. @SpringBootTest
  13. public class UserMapperTest {
  14. @Autowired
  15. private UserMapper userMapper;
  16. @Test
  17. public void testWrapper() {
  18. QueryWrapper<User> wrapper = new QueryWrapper<>();
  19. //SELECT id,name,age FROM tb_user WHERE name = ? OR age = ?
  20. wrapper.eq("name", "jack")
  21. .or()
  22. .eq("age", 24)
  23. .select("id", "name", "age");
  24. List<User> users = this.userMapper.selectList(wrapper);
  25. for (User user : users) {
  26. System.out.println(user);
  27. }
  28. }
  29. }

6. ActiveRecord

ActiveRecord (简称 AR )⼀直⼴受动态语⾔( PHP Ruby 等)的喜爱,⽽ Java 作为准静态语⾔,对于 ActiveRecord 往往只能感叹其优雅,所以我们也在 AR 道路上进⾏了⼀定的探索,希望⼤家能够喜欢。 
什么是 ActiveRecord
ActiveRecord 也属于 ORM (对象关系映射)层,由 Rails 最早提出,遵循标准的 ORM 模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很⼤程度的快速实现模型的操作,⽽且简洁易懂。
ActiveRecord 的主要思想是:
  • 每⼀个数据库表对应创建⼀个类,类的每⼀个对象实例对应于数据库中表的⼀⾏记录;通常 表的每个字段在类中都有相应的Field
  • ActiveRecord同时负责把⾃⼰持久化,在ActiveRecord中封装了对数据库的访问,即 CURD;
  • ActiveRecord是⼀种领域模型(Domain Model),封装了部分业务逻辑;

6.1、开启AR之旅

MP 中,开启 AR ⾮常简单,只需要将实体对象继承 Model 即可。
  1. package com.lagou.mp.pojo;
  2. import com.baomidou.mybatisplus.annotation.IdType;
  3. import com.baomidou.mybatisplus.annotation.TableField;
  4. import com.baomidou.mybatisplus.annotation.TableId;
  5. import com.baomidou.mybatisplus.annotation.TableName;
  6. import com.baomidou.mybatisplus.extension.activerecord.Model;
  7. import lombok.AllArgsConstructor;
  8. import lombok.Data;
  9. import lombok.NoArgsConstructor;
  10. @Data
  11. @NoArgsConstructor
  12. @AllArgsConstructor
  13. public class User extends Model<User> {
  14. private Long id;
  15. private String userName;
  16. private String password;
  17. private String name;
  18. private Integer age;
  19. private String email;
  20. }

6.2、根据主键查询

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class UserMapperTest {
  4. @Autowired
  5. private UserMapper userMapper;
  6. @Test
  7. public void testAR() {
  8. User user = new User();
  9. user.setId(2L);
  10. User user2 = user.selectById();
  11. System.out.println(user2);
  12. }
  13. }

6.3、新增数据

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class UserMapperTest {
  4. @Autowired
  5. private UserMapper userMapper;
  6. @Test
  7. public void testARInsert() {
  8. User user = new User();
  9. user.setName("应颠");
  10. user.setAge(30);
  11. user.setEmail("yingdian@lagou.cn");
  12. boolean insert = user.insert();
  13. System.out.println(insert);
  14. }
  15. }
[main] [com.lagou.mp.mapper.UserMapper.insert]-[DEBUG] == > Preparing: INSERT
INTO tb_user ( name, age, email ) VALUES ( ?, ?, ?, ?, ? )
[main] [com.lagou.mp.mapper.UserMapper.insert]-[DEBUG] == > Parameters: 应癫
(String), 30 (Integer), liubei@lagou.cn(String)
[main] [com.lagou.mp.mapper.UserMapper.insert]-[DEBUG] < == Updates: 1

6.4、更新操作

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class UserMapperTest {
  4. @Autowired
  5. private UserMapper userMapper;
  6. @Test
  7. public void testAR() {
  8. User user = new User();
  9. user.setId(8L);
  10. user.setAge(35);
  11. boolean update = user.updateById();
  12. System.out.println(update);
  13. }
  14. }
结果:
[main] [com.lagou.mp.mapper.UserMapper.updateById]-[DEBUG] == > Preparing:
UPDATE tb_user SET age = ? WHERE id = ?
[main] [com.lagou.mp.mapper.UserMapper.updateById]-[DEBUG] == > Parameters:
35 (Integer), 8 (Long)
[main] [com.lagou.mp.mapper.UserMapper.updateById]-[DEBUG] < == Updates: 1

6.5、删除操作

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class UserMapperTest {
  4. @Autowired
  5. private UserMapper userMapper;
  6. @Test
  7. public void testAR() {
  8. User user = new User();
  9. user.setId(7L);
  10. boolean delete = user.deleteById();
  11. System.out.println(delete);
  12. }
  13. }

结果:

[main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] == > Preparing:
DELETE FROM tb_user WHERE id = ?
[main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] == > Parameters:
7 (Long)
[main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] < == Updates: 1

6.6、根据条件查询

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class UserMapperTest {
  4. @Autowired
  5. private UserMapper userMapper;
  6. @Test
  7. public void testARFindById() {
  8. User user = new User();
  9. QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
  10. userQueryWrapper.le("age","20");
  11. List<User> users = user.selectList(userQueryWrapper);
  12. for (User user1 : users) {
  13. System.out.println(user1);
  14. }
  15. }
  16. }
结果:
User (id = 1 , name = Jone, age = 18 , email = test1@baomidou.com)
User (id = 2 , name = Jack, age = 20 , email = test2@baomidou.com)
User (id = 7 , name = ⼦慕 , age = 18 , email = test@lagou.cn)

7. 插件

7.1mybatis的插件机制

MyBatis 允许你在已映射语句执⾏过程中的某⼀点进⾏拦截调⽤。默认情况下, MyBatis 允许使⽤插件
来拦截的⽅法调⽤包括:
1. Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
2. ParameterHandler (getParameterObject, setParameters)
3. ResultSetHandler (handleResultSets, handleOutputParameters)
4. StatementHandler (prepare, parameterize, batch, update, query)
我们看到了可以拦截 Executor 接⼝的部分⽅法,⽐如 update query commit rollback 等⽅法,还有其他接⼝的⼀些⽅法等。
总体概括为:
1. 拦截执⾏器的⽅法
2. 拦截参数的处理
3. 拦截结果集的处理
4. 拦截 Sql 语法构建的处理
拦截器示例:
  1. package com.lagou.mp.plugins;
  2. import org.apache.ibatis.executor.Executor;
  3. import org.apache.ibatis.mapping.MappedStatement;
  4. import org.apache.ibatis.plugin.*;
  5. import java.util.Properties;
  6. @Intercepts({@Signature(
  7. type= Executor.class,
  8. method = "update",
  9. args = {MappedStatement.class,Object.class})})
  10. public class MyInterceptor implements Interceptor {
  11. @Override
  12. public Object intercept(Invocation invocation) throws Throwable {
  13. //拦截⽅法,具体业务逻辑编写的位置
  14. return invocation.proceed();
  15. }
  16. @Override
  17. public Object plugin(Object target) {
  18. //创建target对象的代理对象,⽬的是将当前拦截器加⼊到该对象中
  19. return Plugin.wrap(target, this);
  20. }
  21. @Override
  22. public void setProperties(Properties properties) {
  23. //属性设置
  24. }
  25. }

注⼊到Spring容器:

  1. /**
  2. * ⾃定义拦截器
  3. */
  4. @Bean
  5. public MyInterceptor myInterceptor(){
  6. return new MyInterceptor();
  7. }

或者通过xml配置,mybatis-config.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <plugins>
  7. <plugin interceptor="com.lagou.mp.plugins.MyInterceptor"></plugin>
  8. </plugins>
  9. </configuration>

7.2、执⾏分析插件

MP 中提供了对 SQL 执⾏的分析的插件,可⽤作阻断全表更新、删除的操作,注意:该插件仅适⽤于开发环境,不适⽤于⽣产环境。
SpringBoot 配置:
  1. @Bean
  2. public SqlExplainInterceptor sqlExplainInterceptor(){
  3. SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();
  4. List<ISqlParser> sqlParserList = new ArrayList<>();
  5. // 攻击 SQL 阻断解析器、加⼊解析链
  6. sqlParserList.add(new BlockAttackSqlParser());
  7. sqlExplainInterceptor.setSqlParserList(sqlParserList);
  8. return sqlExplainInterceptor; }
测试:
  1. @Test
  2. public void testUpdate(){
  3. User user = new User();
  4. user.setAge(20);
  5. int result = this.userMapper.update(user, null);
  6. System.out.println("result = " + result);
  7. }
结果:
Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException:
Prohibition of table update operation
at
com.baomidou.mybatisplus.core.toolkit.ExceptionUtils.mpe(ExceptionUtils.java:4
9)
at com.baomidou.mybatisplus.core.toolkit.Assert.isTrue(Assert.java:38)
at com.baomidou.mybatisplus.core.toolkit.Assert.notNull(Assert.java:72)
at
com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser.processUpdate(
BlockAttackSqlParser.java:45)
at
com.baomidou.mybatisplus.core.parser.AbstractJsqlParser.processParser(Abstract
JsqlParser.java:92)
at
com.baomidou.mybatisplus.core.parser.AbstractJsqlParser.parser(AbstractJsqlPar
ser.java:67)
at
com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler.sqlParser
(AbstractSqlParserHandler.java:76)
at
com.baomidou.mybatisplus.extension.plugins.SqlExplainInterceptor.intercept(Sql
ExplainInterceptor.java:63)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
at com.sun.proxy. $Proxy70 .update(Unknown Source)
at
org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.
java:197)
... 41 more
可以看到,当执⾏全表更新时,会抛出异常,这样有效防⽌了⼀些误操作。

7.3、性能分析插件

性能分析拦截器,⽤于输出每条 SQL 语句及其执⾏时间,可以设置最⼤执⾏时间,超过时间会抛出异常。
该插件只⽤于开发环境,不建议⽣产环境使⽤。
配置:
javaconfig ⽅式
  1. @Bean
  2. public PerformanceInterceptor performanceInterceptor(){
  3. PerformanceInterceptor performanceInterceptor = new
  4. PerformanceInterceptor();
  5. performanceInterceptor.setMaxTime(100);
  6. performanceInterceptor.setFormat(true);
  7. return performanceInterceptor; }
xml ⽅式
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <plugins>
  7. <!-- SQL 执⾏性能分析,开发环境使⽤,线上不推荐。 maxTime 指的是 sql 最⼤执⾏时
  8. ⻓ -->
  9. <plugin
  10. interceptor="com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor
  11. ">
  12. <property name="maxTime" value="100" />
  13. <!--SQL是否格式化 默认false-->
  14. <property name="format" value="true" />
  15. </plugin>
  16. </plugins>
  17. </configuration>
执⾏结果:
Time 11 ms - ID com.lagou.mp.mapper.UserMapper.selectById
Execute SQL
SELECT
id,
user_name,
password,
name,
age,
email
FROM
tb_user
WHERE
id = 7
可以看到,执⾏时间为 11ms 。如果将 maxTime 设置为 1 ,那么,该操作会抛出异常。

7.4、乐观锁插件

7.4.1、主要适⽤场景

意图:
当要更新⼀条记录的时候,希望这条记录没有被别⼈更新
乐观锁实现⽅式:
  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执⾏更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

7.4.2、插件配置

spring xml:
  1. <bean
  2. class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"
  3. />
spring boot:
  1. @Bean
  2. public OptimisticLockerInterceptor optimisticLockerInterceptor() {
  3. return new OptimisticLockerInterceptor();
  4. }

7.4.3、注解实体字段

需要为实体字段添加 @Version 注解。
第⼀步,为表添加 version 字段,并且设置初始值为 1
  1. ALTER TABLE `tb_user`
  2. ADD COLUMN `version` int(10) NULL AFTER `email`;
  3. UPDATE `tb_user` SET `version`='1';

第⼆步,为User实体对象添加version字段,并且添加@Version注解:

  1. @Version
  2. private Integer version;

7.4.4、测试

测试⽤例:
  1. @Test
  2. public void testUpdate(){
  3. User user = new User();
  4. user.setAge(30);
  5. user.setId(2L);
  6. user.setVersion(1); //获取到version为1
  7. int result = this.userMapper.updateById(user);
  8. System.out.println("result = " + result);
  9. }
执⾏⽇志:
main] [com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser]-
[DEBUG] Original SQL: UPDATE tb_user SET age = ?,
version = ? WHERE id = ? AND version = ?
[main] [com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser]-
[DEBUG] parser sql: UPDATE tb_user SET age = ?, version = ? WHERE id = ? AND
version = ?
[main] [org.springframework.jdbc.datasource.DataSourceUtils]-[DEBUG] Fetching
JDBC Connection from DataSource
[main] [org.mybatis.spring.transaction.SpringManagedTransaction]-[DEBUG] JDBC
Connection [HikariProxyConnection@540206885 wrapping
com.mysql.jdbc.JDBC4Connection@27e0f2f5] will not be managed by Spring
[main] [com.lagou.mp.mapper.UserMapper.updateById]-[DEBUG] == > Preparing:
UPDATE tb_user SET age = ?, version = ? WHERE id = ? AND version = ?
[main] [com.lagou.mp.mapper.UserMapper.updateById]-[DEBUG] == > Parameters:
30 (Integer), 2 (Integer), 2 (Long), 1 (Integer)
[main] [com.lagou.mp.mapper.UserMapper.updateById]-[DEBUG] < == Updates: 1
[main] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Closing non transactional
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@30135202]
result = 1
可以看到,更新的条件中有 version 条件,并且更新的 version 2
如果再次执⾏,更新则不成功。这样就避免了多⼈同时更新时导致数据的不⼀致。

7.4.5、特别说明

  • ⽀持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 整数类型下 newVersion = oldVersion + 1
  • newVersion 会回写到 entity
  • 仅⽀持 updateById(id) update(entity, wrapper) ⽅法
  • update(entity, wrapper) ⽅法下, wrapper 不能复⽤!!!

8. Sql 注⼊器

我们已经知道,在 MP 中,通过 AbstractSqlInjector BaseMapper 中的⽅法注⼊到了 Mybatis 容器,这样这些⽅法才可以正常执⾏。
那么,如果我们需要扩充 BaseMapper 中的⽅法,⼜该如何实现呢?
下⾯我们以扩展 findAll ⽅法为例进⾏学习。

8.1、编写MyBaseMapper

  1. package com.lagou.mp.mapper;
  2. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  3. import java.util.List;
  4. public interface MyBaseMapper<T> extends BaseMapper<T> {
  5. List<T> findAll();
  6. }
其他的 Mapper 都可以继承该 Mapper ,这样实现了统⼀的扩展。
如:
  1. package com.lagou.mp.mapper;
  2. import com.lagou.mp.pojo.User;
  3. public interface UserMapper extends MyBaseMapper<User> {
  4. User findById(Long id);
  5. }

8.2、编写MySqlInjector

如果直接继承 AbstractSqlInjector 的话,原有的 BaseMapper 中的⽅法将失效,所以我们选择继承
DefaultSqlInjector 进⾏扩展。
  1. package com.lagou.mp.sqlInjector;
  2. import com.baomidou.mybatisplus.core.injector.AbstractMethod;
  3. import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
  4. import java.util.List;
  5. public class MySqlInjector extends DefaultSqlInjector {
  6. @Override
  7. public List<AbstractMethod> getMethodList() {
  8. List<AbstractMethod> methodList = super.getMethodList();
  9. methodList.add(new FindAll());
  10. // 再扩充⾃定义的⽅法
  11. list.add(new FindAll());
  12. return methodList;
  13. }
  14. }

8.3、编写FindAll

  1. package com.lagou.mp.sqlInjector;
  2. import com.baomidou.mybatisplus.core.enums.SqlMethod;
  3. import com.baomidou.mybatisplus.core.injector.AbstractMethod;
  4. import com.baomidou.mybatisplus.core.metadata.TableInfo;
  5. import org.apache.ibatis.mapping.MappedStatement;
  6. import org.apache.ibatis.mapping.SqlSource;
  7. public class FindAll extends AbstractMethod {
  8. @Override
  9. public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?
  10. > modelClass, TableInfo tableInfo) {
  11. String sqlMethod = "findAll";
  12. String sql = "select * from " + tableInfo.getTableName();
  13. SqlSource sqlSource = languageDriver.createSqlSource(configuration,
  14. sql, modelClass);
  15. return this.addSelectMappedStatement(mapperClass, sqlMethod,
  16. sqlSource, modelClass, tableInfo);
  17. }
  18. }

8.4、注册到Spring容器

  1. /**
  2. * ⾃定义SQL注⼊器
  3. */
  4. @Bean
  5. public MySqlInjector mySqlInjector(){
  6. return new MySqlInjector();
  7. }

8.5、测试

  1. @Test
  2. public void testFindAll(){
  3. List<User> users = this.userMapper.findAll();
  4. for (User user : users) {
  5. System.out.println(user);
  6. }
  7. }
输出的 SQL
[main] [com.lagou.mp.mapper.UserMapper.findAll]-[DEBUG] == > Preparing: select
* from tb_user
[main] [com.lagou.mp.mapper.UserMapper.findAll]-[DEBUG] == > Parameters:
[main] [com.lagou.mp.mapper.UserMapper.findAll]-[DEBUG] < == Total: 10
⾄此,我们实现了全局扩展 SQL 注⼊器。

9. ⾃动填充功能

有些时候我们可能会有这样的需求,插⼊或者更新数据时,希望有些字段可以⾃动填充数据,⽐如密码、version 等。在 MP 中提供了这样的功能,可以实现⾃动填充。

9.1、添加@TableField注解

  1. @TableField(fill = FieldFill.INSERT) //插⼊数据时进⾏填充
  2. private String version;
email 添加⾃动填充功能,在新增数据时有效。
FieldFill 提供了多种模式选择:
  1. public enum FieldFill {
  2. 9.2、编写MyMetaObjectHandler
  3. 9.3、测试
  4. /**
  5. * 默认不处理
  6. */
  7. DEFAULT,
  8. /**
  9. * 插⼊时填充字段
  10. */
  11. INSERT,
  12. /**
  13. * 更新时填充字段
  14. */
  15. UPDATE,
  16. /**
  17. * 插⼊和更新时填充字段
  18. */
  19. INSERT_UPDATE
  20. }

9.2、编写MyMetaObjectHandler

  1. package com.lagou.mp.handler;
  2. import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
  3. import org.apache.ibatis.reflection.MetaObject;
  4. import org.springframework.stereotype.Component;
  5. @Component
  6. public class MyMetaObjectHandler implements MetaObjectHandler {
  7. @Override
  8. public void insertFill(MetaObject metaObject) {
  9. Object password = getFieldValByName("version", metaObject);
  10. if(null == password){
  11. //字段为空,可以进⾏填充
  12. setFieldValByName("version", "123456", metaObject);
  13. }
  14. }
  15. @Override
  16. public void updateFill(MetaObject metaObject) {
  17. }
  18. }

9.3、测试

  1. @Test
  2. public void testInsert(){
  3. User user = new User();
  4. user.setName("冰冰");
  5. user.setAge(30);
  6. user.setVersion(1);
  7. int result = this.userMapper.insert(user);
  8. System.out.println("result = " + result);
  9. }
结果:

10. 逻辑删除

开发系统时,有时候在实现功能时,删除操作需要实现逻辑删除,所谓逻辑删除就是将数据标记为删除,⽽并⾮真正的物理删除(⾮DELETE 操作),查询时需要携带状态条件,确保被标记的数据不被查询到。这样做的⽬的就是避免数据被真正的删除。
MP 就提供了这样的功能,⽅便我们使⽤,接下来我们⼀起学习下。

10.1、修改表结构

  1. ALTER TABLE `tb_user`
  2. ADD COLUMN `deleted` int(1) NULL DEFAULT 0 COMMENT '1代表删除,0代表未删除'
  3. AFTER `version`;
tb_user 表增加 deleted 字段,⽤于表示数据是否被删除, 1 代表删除, 0 代表未删除。
同时,也修改 User 实体,增加 deleted 属性并且添加 @TableLogic 注解:
  1. @TableLogic
  2. private Integer deleted;

10.2、配置

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

10.3、测试

  1. @Test
  2. public void testDeleteById(){
  3. this.userMapper.deleteById(2L);
  4. }
执⾏的 SQL
[main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] == > Preparing:
UPDATE tb_user SET deleted = 1 WHERE id = ? AND deleted = 0
[main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] == > Parameters:
2 (Long)
[main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] < == Updates: 1

测试查询:
  1. @Test
  2. public void testSelectById(){
  3. User user = this.userMapper.selectById(2L);
  4. System.out.println(user);
  5. }
执⾏的 SQL
[main] [com.lagou.mp.mapper.UserMapper.selectById]-[DEBUG] == > Preparing:
SELECT id,user_name,password,name,age,email,version,deleted FROM tb_user WHERE
id = ? AND deleted = 0
[main] [com.lagou.mp.mapper.UserMapper.selectById]-[DEBUG] == > Parameters:
2 (Long)
[main] [com.lagou.mp.mapper.UserMapper.selectById]-[DEBUG] < == Total: 0
可⻅,已经实现了逻辑删除。

11. 代码⽣成器

AutoGenerator MyBatis-Plus 的代码⽣成器,通过 AutoGenerator 可以快速⽣成 Entity
Mapper Mapper XML Service Controller 等各个模块的代码,极⼤的提升了开发效率。

11.1、创建⼯程

pom.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. https://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <modelVersion>4.0.0</modelVersion>
  7. <parent>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-starter-parent</artifactId>
  10. <version>2.3.4.RELEASE</version>
  11. <relativePath/> <!-- lookup parent from repository -->
  12. </parent>
  13. <groupId>com.lagou</groupId>
  14. <artifactId>lagou-mp-generator</artifactId>
  15. <version>0.0.1-SNAPSHOT</version>
  16. <name>lagou-mp-generator</name>
  17. <description>Demo project for Spring Boot</description>
  18. <properties>
  19. <java.version>11</java.version>
  20. </properties>
  21. <dependencies>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-test</artifactId>
  25. <scope>test</scope>
  26. </dependency>
  27. <!--mybatis-plus的springboot⽀持-->
  28. <dependency>
  29. <groupId>com.baomidou</groupId>
  30. <artifactId>mybatis-plus-boot-starter</artifactId>
  31. <version>3.1.1</version>
  32. </dependency>
  33. <dependency>
  34. <groupId>com.baomidou</groupId>
  35. <artifactId>mybatis-plus-generator</artifactId>
  36. <version>3.1.1</version>
  37. </dependency>
  38. <dependency>
  39. <groupId>org.springframework.boot</groupId>
  40. <artifactId>spring-boot-starter-freemarker</artifactId>
  41. </dependency>
  42. <!--mysql驱动-->
  43. <dependency>
  44. <groupId>mysql</groupId>
  45. <artifactId>mysql-connector-java</artifactId>
  46. <version>5.1.47</version>
  47. </dependency>
  48. <dependency>
  49. <groupId>org.slf4j</groupId>
  50. <artifactId>slf4j-log4j12</artifactId>
  51. </dependency>
  52. <dependency>
  53. <groupId>org.springframework.boot</groupId>
  54. <artifactId>spring-boot-starter-web</artifactId>
  55. </dependency>
  56. <!--简化代码的⼯具包-->
  57. <dependency>
  58. <groupId>org.projectlombok</groupId>
  59. <artifactId>lombok</artifactId>
  60. <optional>true</optional>
  61. </dependency>
  62. </dependencies>
  63. <build>
  64. <plugins>
  65. <plugin>
  66. <groupId>org.springframework.boot</groupId>
  67. <artifactId>spring-boot-maven-plugin</artifactId>
  68. </plugin>
  69. </plugins>
  70. </build>
  71. </project>

11.2、代码

  1. package com.lagou.mp.generator;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.Scanner;
  5. import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
  6. import com.baomidou.mybatisplus.core.toolkit.StringPool;
  7. import com.baomidou.mybatisplus.core.toolkit.StringUtils;
  8. import com.baomidou.mybatisplus.generator.AutoGenerator;
  9. import com.baomidou.mybatisplus.generator.InjectionConfig;
  10. import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
  11. import com.baomidou.mybatisplus.generator.config.FileOutConfig;
  12. import com.baomidou.mybatisplus.generator.config.GlobalConfig;
  13. import com.baomidou.mybatisplus.generator.config.PackageConfig;
  14. import com.baomidou.mybatisplus.generator.config.StrategyConfig;
  15. import com.baomidou.mybatisplus.generator.config.TemplateConfig;
  16. import com.baomidou.mybatisplus.generator.config.po.TableInfo;
  17. import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
  18. import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
  19. /**
  20. * <p>
  21. * mysql 代码⽣成器演示例⼦
  22. * </p>
  23. */
  24. public class MysqlGenerator {
  25. /**
  26. * <p>
  27. * 读取控制台内容
  28. * </p>
  29. */
  30. public static String scanner(String tip) {
  31. Scanner scanner = new Scanner(System.in);
  32. StringBuilder help = new StringBuilder();
  33. help.append("请输⼊" + tip + ":");
  34. System.out.println(help.toString());
  35. if (scanner.hasNext()) {
  36. String ipt = scanner.next();
  37. if (StringUtils.isNotEmpty(ipt)) {
  38. return ipt;
  39. }
  40. }
  41. throw new MybatisPlusException("请输⼊正确的" + tip + "!");
  42. }
  43. /**
  44. * RUN THIS
  45. */
  46. public static void main(String[] args) {
  47. // 代码⽣成器
  48. AutoGenerator mpg = new AutoGenerator();
  49. // 全局配置
  50. GlobalConfig gc = new GlobalConfig();
  51. String projectPath = System.getProperty("user.dir");
  52. gc.setOutputDir(projectPath + "/src/main/java");
  53. gc.setAuthor("lagou");
  54. gc.setOpen(false);
  55. mpg.setGlobalConfig(gc);
  56. // 数据源配置
  57. DataSourceConfig dsc = new DataSourceConfig();
  58. dsc.setUrl("jdbc:mysql://127.0.0.1:3306/mp?
  59. useUnicode=true&useSSL=false&characterEncoding=utf8");
  60. // dsc.setSchemaName("public");
  61. dsc.setDriverName("com.mysql.jdbc.Driver");
  62. dsc.setUsername("root");
  63. dsc.setPassword("root");
  64. mpg.setDataSource(dsc);
  65. // 包配置
  66. PackageConfig pc = new PackageConfig();
  67. pc.setModuleName(scanner("模块名"));
  68. pc.setParent("com.lagou.mp.generator");
  69. mpg.setPackageInfo(pc);
  70. // ⾃定义配置
  71. InjectionConfig cfg = new InjectionConfig() {
  72. @Override
  73. public void initMap() {
  74. // to do nothing
  75. }
  76. };
  77. List<FileOutConfig> focList = new ArrayList<>();
  78. focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
  79. @Override
  80. public String outputFile(TableInfo tableInfo) {
  81. // ⾃定义输⼊⽂件名称
  82. return projectPath + "/lagou-mpgenerator/src/main/resources/mapper/" + pc.getModuleName()
  83. + "/" + tableInfo.getEntityName() + "Mapper" +
  84. StringPool.DOT_XML;
  85. }
  86. });
  87. cfg.setFileOutConfigList(focList);
  88. mpg.setCfg(cfg);
  89. mpg.setTemplate(new TemplateConfig().setXml(null));
  90. // 策略配置
  91. StrategyConfig strategy = new StrategyConfig();
  92. strategy.setNaming(NamingStrategy.underline_to_camel);
  93. strategy.setColumnNaming(NamingStrategy.underline_to_camel);
  94. //strategy.setSuperEntityClass("com.baomidou.mybatisplus.samples.generator.common.BaseEntity");
  95. strategy.setEntityLombokModel(true);
  96. //strategy.setSuperControllerClass("com.baomidou.mybatisplus.samples.generator.common.BaseController");
  97. strategy.setInclude(scanner("表名"));
  98. strategy.setSuperEntityColumns("id");
  99. strategy.setControllerMappingHyphenStyle(true);
  100. strategy.setTablePrefix(pc.getModuleName() + "_");
  101. mpg.setStrategy(strategy);
  102. // 选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!
  103. mpg.setTemplateEngine(new FreemarkerTemplateEngine());
  104. mpg.execute();
  105. }
  106. }

11.3、测试

代码已⽣成:

实体对象:

12. MybatisX 快速开发插件

MybatisX 是⼀款基于 IDEA 的快速开发插件,为效率⽽⽣。
安装⽅法:打开 IDEA ,进⼊ File -> Settings -> Plugins -> Browse Repositories ,输⼊ mybatisx 搜索并安装。
功能:
  • Java XML 调回跳转
  • Mapper ⽅法⾃动⽣成 XML

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/407564
推荐阅读
相关标签
  

闽ICP备14008679号