准备:

1、简介

官网:http://mp.baomidou.com/ 参考教程http://mp.baomidou.com/guide/ MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简发、提高效率而生。

2、特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer2005、SQLServer 等多种数据库
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 XML 热加载:Mapper 对应的 XML 支持热加载,对于简单的 CRUD 操作,甚至可以无 XML 启动
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 支持关键词自动转义:支持数据库关键词(order、key……)自动转义,还可自定义关键词
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
  • 内置 Sql 注入剥离器:支持 Sql 注入剥离,有效预防 Sql 注入攻击

    快速开始参考http://mp.baomidou.com/guide/quick-start.html 测试项目: mybatis_plus 数据库:mybatis_plus

一、创建并初始化数据库

1、创建数据库:

mybatis_plus

2、创建 User 表

其表结构如下:

id name age email
1 张三 18 test1@163.com
2 李四 20 test2@163.com
3 王五 28 test3@163.com
4 赵六 21 test4@163.com
5 钱七 24 test5@163.com

其对应的数据库 Schema 脚本如下:

  1. CREATE TABLE user
  2. (
  3. id BIGINT(20) NOT NULL COMMENT '主键ID',
  4. name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
  5. age INT(11) NULL DEFAULT NULL COMMENT '年龄',
  6. email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
  7. PRIMARY KEY (id)
  8. );

其对应的数据库 Data 脚本如下:

  1. DELETE FROM user;
  2. INSERT INTO user (id, name, age, email) VALUES
  3. (1, '张三', 18, 'test1@163.com'),
  4. (2, '李四', 20, 'test2@163.com'),
  5. (3, '王五', 28, 'test3@163.com'),
  6. (4, '赵六', 21, 'test4@163.com'),
  7. (5, '钱七', 24, 'test5@163.com');

二、初始化工程

使用 Spring Initializr 快速初始化一个 Spring Boot 工程
Group:com.zelin
Artifact:mybatis-plus
版本:2.2.1.RELEASE

三、添加依赖

1、引入依赖

使用 Spring Initializr 快速初始化一个 Spring Boot 工程
Group:com.zelin
Artifact:mybatis-plus
版本:2.2.1.RELEASE

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-test</artifactId>
  9. <scope>test</scope>
  10. <exclusions>
  11. <exclusion>
  12. <groupId>org.junit.vintage</groupId>
  13. <artifactId>junit-vintage-engine</artifactId>
  14. </exclusion>
  15. </exclusions>
  16. </dependency>
  17. <!--mybatis-plus-->
  18. <dependency>
  19. <groupId>com.baomidou</groupId>
  20. <artifactId>mybatis-plus-boot-starter</artifactId>
  21. <version>3.0.5</version>
  22. </dependency>
  23. <!--mysql-->
  24. <dependency>
  25. <groupId>mysql</groupId>
  26. <artifactId>mysql-connector-java</artifactId>
  27. </dependency>
  28. <!--lombok用来简化实体类-->
  29. <dependency>
  30. <groupId>org.projectlombok</groupId>
  31. <artifactId>lombok</artifactId>
  32. </dependency>
  33. </dependencies>

注意:引入 MyBatis-Plus 之后请不要再次引入 MyBatis 以及 MyBatis-Spring,以避免因版本差异导致的问题。

2、idea中安装lombok插件

(1)idea2020版本
image.png

四、配置

在 application.properties 配置文件中添加 MySQL 数据库的相关配置:
mysql5

  1. #mysql数据库连接
  2. spring.datasource.driver-class-name=com.mysql.jdbc.Driver
  3. spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus
  4. spring.datasource.username=root
  5. spring.datasource.password=root

mysql8以上(spring boot 2.1)
注意:driver和url的变化

  1. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  2. spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
  3. spring.datasource.username=root
  4. spring.datasource.password=123456

注意:

1、这里的 url 使用了 ?serverTimezone=GMT%2B8 后缀,因为Spring Boot 2.1 集成了 8.0版本的jdbc驱动,这个版本的 jdbc 驱动需要添加这个后缀,否则运行测试用例报告如下错误: java.sql.SQLException: The server time zone value ‘Öйú±ê׼ʱ¼ä’ is unrecognized or represents more 2、这里的 driver-class-name 使用了 com.mysql.cj.jdbc.Driver ,在 jdbc 8 中 建议使用这个驱动,之前的 com.mysql.jdbc.Driver 已经被废弃,否则运行测试用例的时候会有 WARN 信息

五、编写代码

1、主类
在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹
注意:扫描的包名根据实际情况修改

  1. @SpringBootApplication
  2. @MapperScan("com.zelin.mybatisplus.mapper")
  3. public class MybatisPlusApplication {
  4. ......
  5. }

2、实体

创建包 entity 编写实体类 User.java(此处使用了 Lombok 简化代码)

  1. @Data
  2. public class User {
  3. private Long id;
  4. private String name;
  5. private Integer age;
  6. private String email;
  7. }

查看编译结果
image.png
Lombok使用参考:
https://blog.csdn.net/motui/article/details/79012846

3、mapper

创建包 mapper 编写Mapper 接口: UserMapper.java

  1. public interface UserMapper extends BaseMapper<User> {
  2. }

六、开始使用

添加测试类,进行功能测试:

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class MybatisPlusApplicationTests {
  4. @Autowired
  5. private UserMapper userMapper;
  6. @Test
  7. public void testSelectList() {
  8. System.out.println(("----- selectAll method test ------"));
  9. //UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper
  10. //所以不填写就是无任何条件
  11. List<User> users = userMapper.selectList(null);
  12. users.forEach(System.out::println);
  13. }
  14. }

注意:

IDEA在 userMapper 处报错,因为找不到注入的对象,因为类是动态创建的,但是程序可以正确的执行。为了避免报错,可以在 dao 层 的接口上添加 @Repository 注解控制台输出

  1. User(id=1, name=Jone, age=18, email=张三@163.com)
  2. User(id=2, name=Jack, age=20, email=李四@163.com)
  3. User(id=3, name=Tom, age=28, email=王五@163.com)
  4. User(id=4, name=Sandy, age=21, email=赵六@163.com)
  5. User(id=5, name=Billie, age=24, email=钱七@163.com)

通过以上几个简单的步骤,我们就实现了 User 表的 CRUD 功能,甚至连 XML 文件都不用编写!

七、配置日志

查看sql输出日志

  1. #mybatis日志
  2. mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
  3. #可以使用
  4. logging.level.com.zelin=debug

八、insert

1、插入操作

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class CRUDTests {
  4. @Autowired
  5. private UserMapper userMapper;
  6. @Test
  7. public void testInsert(){
  8. User user = new User();
  9. user.setName("Helen");
  10. user.setAge(18);
  11. user.setEmail("55317332@qq.com");
  12. int result = userMapper.insert(user);
  13. System.out.println(result); //影响的行数
  14. System.out.println(user); //id自动回填
  15. }
  16. }

注意:数据库插入id值默认为:全局唯一id
image.png

2、主键策略

(1)ID_WORKER
MyBatis-Plus默认的主键策略是:IDWORKER 全局唯一ID_
参考资料:分布式系统唯一ID生成方案汇总:https://www.cnblogs.com/haoxinyue/p/5208136.html
(2)自增策略

  • 要想主键自增需要配置如下主键策略

    • 需要在创建数据表的时候设置主键自增
    • 实体字段中配置 @TableId(type = IdType.AUTO)

      1. @TableId(type = IdType.AUTO)
      2. private Long id;

      要想影响所有实体的配置,可以设置全局主键配置

      1. #全局设置主键生成策略
      2. mybatis-plus.global-config.db-config.id-type=auto

      其它主键策略:分析 IdType 源码可知

      九、update

      1、根据Id更新操作

      注意:update时生成的sql自动是动态sql:UPDATE user SET age=? WHERE id=?

      1. @Test
      2. public void testUpdateById(){
      3. User user = new User();
      4. user.setId(1L);
      5. user.setAge(28);
      6. int result = userMapper.updateById(user);
      7. System.out.println(result);
      8. }

      2、自动填充

      项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。
      我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作:
      (1)数据库表中添加自动填充字段
      在User表中添加datetime类型的新的字段 create_time、update_time
      (2)实体上添加注解

      1. @Data
      2. public class User {
      3. ......
      4. @TableField(fill = FieldFill.INSERT)
      5. private Date createTime;
      6. //@TableField(fill = FieldFill.UPDATE)
      7. @TableField(fill = FieldFill.INSERT_UPDATE)
      8. private Date updateTime;
      9. }

      (3)实现元对象处理器接口
      注意:不要忘记添加 @Component 注解 ```java package com.atguigu.mybatisplus.handler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.util.Date;

@Component public class MyMetaObjectHandler implements MetaObjectHandler {

  1. private static final Logger LOGGER = LoggerFactory.getLogger(MyMetaObjectHandler.class);
  2. @Override
  3. public void insertFill(MetaObject metaObject) {
  4. LOGGER.info("start insert fill ....");
  5. this.setFieldValByName("createTime", new Date(), metaObject);
  6. this.setFieldValByName("updateTime", new Date(), metaObject);
  7. }
  8. @Override
  9. public void updateFill(MetaObject metaObject) {
  10. LOGGER.info("start update fill ....");
  11. this.setFieldValByName("updateTime", new Date(), metaObject);
  12. }

}

  1. **(4)测试**
  2. <a name="rSbHT"></a>
  3. ## 3、乐观锁
  4. **主要适用场景:**当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新<br />**乐观锁实现方式:**
  5. - 取出记录时,获取当前version
  6. - 更新时,带上这个version
  7. - 执行更新时, set version = newVersion where version = oldVersion
  8. - 如果version不对,就更新失败
  9. **(1)数据库中添加version字段**
  10. ```sql
  11. ALTER TABLE `user` ADD COLUMN `version` INT

image.png
(2)实体类添加version字段
并添加 @Version 注解

  1. @Version
  2. @TableField(fill = FieldFill.INSERT)
  3. private Integer version;

(3)元对象处理器接口添加version的insert默认值

  1. @Override
  2. public void insertFill(MetaObject metaObject) {
  3. ......
  4. this.setFieldValByName("version", 1, metaObject);
  5. }

特别说明:

  • 支持的数据类型只有 int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 整数类型下 newVersion = oldVersion + 1
  • newVersion 会回写到 entity 中
  • 仅支持 updateById(id) 与 update(entity, wrapper) 方法
  • 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
  • 测试乐观锁时,需要同时传入version这个字段的值。

(4)在 MybatisPlusConfig 中注册 Bean
创建配置类

  1. package com.atguigu.mybatisplus.config;
  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. import org.springframework.transaction.annotation.EnableTransactionManagement;
  7. @EnableTransactionManagement
  8. @Configuration
  9. @MapperScan("com.zelin.mybatis_plus.mapper")
  10. public class MybatisPlusConfig {
  11. /**
  12. * 乐观锁插件
  13. */
  14. @Bean
  15. public OptimisticLockerInterceptor optimisticLockerInterceptor() {
  16. return new OptimisticLockerInterceptor();
  17. }
  18. }

(5)测试乐观锁可以修改成功
测试后分析打印的sql语句,将version的数值进行了加1操作

  1. /**
  2. * 测试 乐观锁插件
  3. */
  4. @Test
  5. public void testOptimisticLocker() {
  6. //查询
  7. User user = userMapper.selectById(1L);
  8. //修改数据
  9. user.setName("Helen Yao");
  10. user.setEmail("helen@qq.com");
  11. //执行更新
  12. userMapper.updateById(user);
  13. }

(5)测试乐观锁修改失败

  1. /**
  2. * 测试乐观锁插件 失败
  3. */
  4. @Test
  5. public void testOptimisticLockerFail() {
  6. //查询
  7. User user = userMapper.selectById(1L);
  8. //修改数据
  9. user.setName("Helen Yao1");
  10. user.setEmail("helen@qq.com1");
  11. //模拟取出数据后,数据库中version实际数据比取出的值大,即已被其它线程修改并更新了version
  12. user.setVersion(user.getVersion() - 1);
  13. //执行更新
  14. userMapper.updateById(user);
  15. }

十、select

1、根据id查询记录

  1. @Test
  2. public void testSelectById(){
  3. User user = userMapper.selectById(1L);
  4. System.out.println(user);
  5. }

2、通过多个id批量查询

完成了动态sql的foreach的功能

  1. @Test
  2. public void testSelectBatchIds(){
  3. List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
  4. users.forEach(System.out::println);
  5. }

3、简单的条件查询

通过map封装查询条件

  1. @Test
  2. public void testSelectByMap(){
  3. HashMap<String, Object> map = new HashMap<>();
  4. map.put("name", "Helen");
  5. map.put("age", 18);
  6. List<User> users = userMapper.selectByMap(map);
  7. users.forEach(System.out::println);
  8. }

注意:

map中的key对应的是数据库中的列名。例如数据库user_id,实体类是userId,这时map的key需要填写user_id

4、分页

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能
(1)创建配置类
此时可以删除主类中的 @MapperScan 扫描注解

  1. /**
  2. * 分页插件
  3. */
  4. @Bean
  5. public PaginationInterceptor paginationInterceptor() {
  6. return new PaginationInterceptor();
  7. }

(2)测试selectPage分页
测试:最终通过page对象获取相关数据

  1. @Test
  2. public void testSelectPage() {
  3. Page<User> page = new Page<>(1,5);
  4. userMapper.selectPage(page, null);
  5. page.getRecords().forEach(System.out::println);
  6. System.out.println(page.getCurrent());
  7. System.out.println(page.getPages());
  8. System.out.println(page.getSize());
  9. System.out.println(page.getTotal());
  10. System.out.println(page.hasNext());
  11. System.out.println(page.hasPrevious());
  12. }

控制台sql语句打印:SELECT id,name,age,email,create_time,update_time FROM user LIMIT 0,5
(3)测试selectMapsPage分页:结果集是Map

  1. @Test
  2. public void testSelectMapsPage() {
  3. Page<User> page = new Page<>(1, 5);
  4. IPage<Map<String, Object>> mapIPage = userMapper.selectMapsPage(page, null);
  5. //注意:此行必须使用 mapIPage 获取记录列表,否则会有数据类型转换错误
  6. mapIPage.getRecords().forEach(System.out::println);
  7. System.out.println(page.getCurrent());
  8. System.out.println(page.getPages());
  9. System.out.println(page.getSize());
  10. System.out.println(page.getTotal());
  11. System.out.println(page.hasNext());
  12. System.out.println(page.hasPrevious());
  13. }

十一、delete

1、根据id删除记录

  1. @Test
  2. public void testDeleteById(){
  3. int result = userMapper.deleteById(8L);
  4. System.out.println(result);
  5. }

2、批量删除

  1. @Test
  2. public void testDeleteBatchIds() {
  3. int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10));
  4. System.out.println(result);
  5. }

3、简单的条件查询删除

  1. @Test
  2. public void testDeleteByMap() {
  3. HashMap<String, Object> map = new HashMap<>();
  4. map.put("name", "Helen");
  5. map.put("age", 18);
  6. int result = userMapper.deleteByMap(map);
  7. System.out.println(result);
  8. }

4、逻辑删除

  • 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
  • 逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录

**(1)数据库中添加 deleted字段

**

  1. ALTER TABLE `user` ADD COLUMN `deleted` tinyint

image.png
2)实体类添加deleted 字段
并加上 @TableLogic 注解 和 @TableField(fill = FieldFill.INSERT) 注解

  1. @TableLogic
  2. @TableField(fill = FieldFill.INSERT)
  3. private Integer deleted;

(3)元对象处理器接口添加deleted的insert默认值

  1. @Override
  2. public void insertFill(MetaObject metaObject) {
  3. ......
  4. this.setFieldValByName("deleted", 0, metaObject);
  5. }

(4)application.properties 加入配置
此为默认值,如果你的默认值和mp默认的一样,该配置可无

  1. mybatis-plus.global-config.db-config.logic-delete-value=1
  2. mybatis-plus.global-config.db-config.logic-not-delete-value=0

(5)在 MybatisPlusConfig 中注册 Bean

  1. @Bean
  2. public ISqlInjector sqlInjector() {
  3. return new LogicSqlInjector();
  4. }

(6)测试逻辑删除

  • 测试后发现,数据并没有被删除,deleted字段的值由0变成了1
  • 测试后分析打印的sql语句,是一条update
  • 注意:被删除数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作

    1. /**
    2. * 测试 逻辑删除
    3. */
    4. @Test
    5. public void testLogicDelete() {
    6. int result = userMapper.deleteById(1L);
    7. System.out.println(result);
    8. }

    (7)测试逻辑删除后的查询
    MyBatis Plus中查询操作也会自动添加逻辑删除字段的判断

    1. /**
    2. * 测试 逻辑删除后的查询:
    3. * 不包括被逻辑删除的记录
    4. */
    5. @Test
    6. public void testLogicDeleteSelect() {
    7. User user = new User();
    8. List<User> users = userMapper.selectList(null);
    9. users.forEach(System.out::println);
    10. }

    测试后分析打印的sql语句,包含 WHERE deleted=0

    1. SELECT id,name,age,email,create_time,update_time,deleted FROM user WHERE deleted=0

    十二、性能分析

    性能分析拦截器,用于输出每条 SQL 语句及其执行时间
    SQL 性能执行分析,开发环境使用,超过指定时间,停止运行。有助于发现问题

    1、配置插件

    (1)参数说明
    参数:maxTime: SQL 执行最大时长,超过自动停止运行,有助于发现问题。
    参数:format: SQL是否格式化,默认false。
    (2)在 MybatisPlusConfig 中配置

    1. /**
    2. * SQL 执行性能分析插件
    3. * 开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长
    4. */
    5. @Bean
    6. @Profile({"dev","test"})// 设置 dev test 环境开启
    7. public PerformanceInterceptor performanceInterceptor() {
    8. PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
    9. performanceInterceptor.setMaxTime(100);//ms,超过此处设置的ms则sql不执行
    10. performanceInterceptor.setFormat(true);
    11. return performanceInterceptor;
    12. }

    (3)Spring Boot 中设置dev环境

    1. #环境设置:dev、test、prod
    2. spring.profiles.active=dev

    可以针对各环境新建不同的配置文件application-dev.properties、application-test.properties、application-prod.properties 也可以自定义环境名称:如test1、test2

2、测试

(1)常规测试

  1. /**
  2. * 测试 性能分析插件
  3. */
  4. @Test
  5. public void testPerformance() {
  6. User user = new User();
  7. user.setName("我是Helen");
  8. user.setEmail("helen@sina.com");
  9. user.setAge(18);
  10. userMapper.insert(user);
  11. }

输出:
image.png
(2)将maxTime 改小之后再次进行测试

  1. performanceInterceptor.setMaxTime(5);//ms,超过此处设置的ms不执行

如果执行时间过长,则抛出异常:The SQL execution time is too large,
输出:
image.png

十三、其它

如果想进行复杂条件查询,那么需要使用条件构造器 Wapper,涉及到如下方法
1、delete
2、selectOne
3、selectCount
4、selectList
5、selectMaps
6、selectObjs
7、update

十四、wapper介绍

image.png

说明: Wrapper : 条件构造抽象类,最顶端父类 AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件 QueryWrapper : Entity 对象封装操作类,不是用lambda语法 UpdateWrapper : Update 条件封装,用于Entity对象更新操作 AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。 LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper LambdaUpdateWrapper : Lambda 更新封装Wrapper

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class QueryWrapperTests {
  4. @Autowired
  5. private UserMapper userMapper;
  6. }

十五、AbstractWrapper

注意:以下条件构造器的方法入参中的 column均表示数据库字段

1、ge、gt、le、lt、isNull、isNotNull

  1. @Test
  2. public void testDelete() {
  3. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  4. queryWrapper
  5. .isNull("name")
  6. .ge("age", 12)
  7. .isNotNull("email");
  8. int result = userMapper.delete(queryWrapper);
  9. System.out.println("delete return count = " + result);
  10. }

SQL:

  1. UPDATE user SET deleted=1 WHERE deleted=0 AND name IS NULL AND age >= ? AND email IS NOT NULL

2、eq、ne

注意:seletOne返回的是一条实体记录,当出现多条时会报错

  1. @Test
  2. public void testSelectOne() {
  3. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  4. queryWrapper.eq("name", "Tom");
  5. User user = userMapper.selectOne(queryWrapper);
  6. System.out.println(user);
  7. }
  1. SELECT id,name,age,email,create_time,update_time,deleted,version FROM user WHERE deleted=0 AND name = ?

3、between、notBetween

包含大小边界

  1. @Test
  2. public void testSelectCount() {
  3. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  4. queryWrapper.between("age", 20, 30);
  5. Integer count = userMapper.selectCount(queryWrapper);
  6. System.out.println(count);
  7. }
  1. SELECT COUNT(1) FROM user WHERE deleted=0 AND age BETWEEN ? AND ?

4、allEq

  1. @Test
  2. public void testSelectList() {
  3. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  4. Map<String, Object> map = new HashMap<>();
  5. map.put("id", 2);
  6. map.put("name", "Jack");
  7. map.put("age", 20);
  8. queryWrapper.allEq(map);
  9. List<User> users = userMapper.selectList(queryWrapper);
  10. users.forEach(System.out::println);
  11. }
  1. SELECT id,name,age,email,create_time,update_time,deleted,version
  2. FROM user WHERE deleted=0 AND name = ? AND id = ? AND age = ?

5、like、notLike、likeLeft、likeRight

selectMaps返回Map集合列表

  1. @Test
  2. public void testSelectMaps() {
  3. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  4. queryWrapper
  5. .notLike("name", "e")
  6. .likeRight("email", "t");
  7. List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表
  8. maps.forEach(System.out::println);
  9. }
  1. SELECT id,name,age,email,create_time,update_time,deleted,version
  2. FROM user WHERE deleted=0 AND name NOT LIKE ? AND email LIKE ?

6、in、notIn、inSql、notinSql、exists、notExists

in、notIn:

  1. notIn("age",{1,2,3})--->age not in (1,2,3)notIn("age", 1, 2, 3)--->age not in (1,2,3)

inSql、notinSql:可以实现子查询

  • 例: inSql(“age”, “1,2,3,4,5,6”)—->age in (1,2,3,4,5,6)
  • 例: inSql(“id”, “select id from table where id < 3”)—->id in (select id from table where id < 3)

    1. @Test
    2. public void testSelectObjs() {
    3. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    4. //queryWrapper.in("id", 1, 2, 3);
    5. queryWrapper.inSql("id", "select id from user where id < 3");
    6. List<Object> objects = userMapper.selectObjs(queryWrapper);//返回值是Object列表
    7. objects.forEach(System.out::println);
    8. }
    1. SELECT id,name,age,email,create_time,update_time,deleted,version
    2. FROM user WHERE deleted=0 AND id IN (select id from user where id < 3)

    7、or、and

    注意:这里使用的是 UpdateWrapper
    不调用or则默认为使用 and连

    1. @Test
    2. public void testUpdate1() {
    3. //修改值
    4. User user = new User();
    5. user.setAge(99);
    6. user.setName("Andy");
    7. //修改条件
    8. UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
    9. userUpdateWrapper
    10. .like("name", "h")
    11. .or()
    12. .between("age", 20, 30);
    13. int result = userMapper.update(user, userUpdateWrapper);
    14. System.out.println(result);
    15. }
    1. UPDATE user SET name=?, age=?, update_time=? WHERE deleted=0 AND name LIKE ? OR age BETWEEN ? AND ?

    8、嵌套or、嵌套and

    这里使用了lambda表达式,or中的表达式最后翻译成sql时会被加上圆括号 ```java @Test public void testUpdate2() {

  1. //修改值
  2. User user = new User();
  3. user.setAge(99);
  4. user.setName("Andy");
  5. //修改条件
  6. UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
  7. userUpdateWrapper
  8. .like("name", "h")
  9. .or(i -> i.eq("name", "李白").ne("age", 20));
  10. int result = userMapper.update(user, userUpdateWrapper);
  11. System.out.println(result);

}

  1. ```sql
  2. UPDATE user SET name=?, age=?, update_time=? WHERE deleted=0 AND name LIKE ? OR ( name = ? AND age <> ? )

9、orderBy、orderByDesc、orderByAsc

  1. @Test
  2. public void testSelectListOrderBy() {
  3. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  4. queryWrapper.orderByDesc("id");
  5. List<User> users = userMapper.selectList(queryWrapper);
  6. users.forEach(System.out::println);
  7. }
  1. SELECT id,name,age,email,create_time,update_time,deleted,version
  2. FROM user WHERE deleted=0 ORDER BY id DESC

10、last

直接拼接到 sql 的最后
注意:只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用

  1. @Test
  2. public void testSelectListLast() {
  3. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  4. queryWrapper.last("limit 1");
  5. List<User> users = userMapper.selectList(queryWrapper);
  6. users.forEach(System.out::println);
  7. }
  1. SELECT id,name,age,email,create_time,update_time,deleted,version
  2. FROM user WHERE deleted=0 limit 1

11、指定要查询的列

  1. @Test
  2. public void testSelectListColumn() {
  3. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  4. queryWrapper.select("id", "name", "age");
  5. List<User> users = userMapper.selectList(queryWrapper);
  6. users.forEach(System.out::println);
  7. }
  1. SELECT id,name,age FROM user WHERE deleted=0

12、set、setSql

最终的sql会合并 user.setAge(),以及 userUpdateWrapper.set() 和 setSql() 中 的字段

  1. @Test
  2. public void testUpdateSet() {
  3. //修改值
  4. User user = new User();
  5. user.setAge(99);
  6. //修改条件
  7. UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
  8. userUpdateWrapper
  9. .like("name", "h")
  10. .set("name", "老李头")//除了可以查询还可以使用set设置修改的字段
  11. .setSql(" email = '123@qq.com'");//可以有子查询
  12. int result = userMapper.update(user, userUpdateWrapper);
  13. }
  1. UPDATE user SET age=?, update_time=?, name=?, email = '123@qq.com' WHERE deleted=0 AND name LIKE ?