美文网首页Java
Mybatis-Plus极速入门

Mybatis-Plus极速入门

作者: Tian_Peng | 来源:发表于2020-11-08 23:58 被阅读0次

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

    特性

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

    支持数据库

    • mysql 、mariadb 、oracle 、db2 、h2 、hsql 、sqlite 、postgresql 、sqlserver 、presto 、Gauss 、Firebird

    • Phoenix 、clickhouse 、Sybase ASE 、 OceanBase 、达梦数据库 、虚谷数据库 、人大金仓数据库 、南大通用数据库 、

    框架结构

    framework

    快速开始

    以springboot项目为例

    引入mybatisPlus的依赖:
    <!-- mybatis-plus -->
    <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.4.0</version>
    </dependency>
    

    完整依赖如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.5.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.tp</groupId>
        <artifactId>demo-mp</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>demo-mp</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <!-- web -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!-- mysql驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <!-- lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional> <!-- 标识依赖不会传递 -->
            </dependency>
            <!-- druid -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.2.1</version>
            </dependency>
            <!-- mybatis-plus -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.4.0</version>
            </dependency>
            <!-- test -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    
    配置数据库连接信息
    server:
      port: 7269
    spring:
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
          url: jdbc:mysql://localhost:3306/mybatis_plus_demo?useSSL=true&serverTimezone=GMT%2B8
          username: root
          password: tp123456
    logging:
      level:
        root: info
        com.tp: debug
    
    创建一个数据库表
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for USER
    -- ----------------------------
    DROP TABLE IF EXISTS `USER`;
    CREATE TABLE `USER` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
      `name` varchar(30) DEFAULT NULL COMMENT '姓名',
      `age` int(11) DEFAULT NULL COMMENT '年龄',
      `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
      `manager_id` bigint(20) DEFAULT NULL COMMENT '直属上级ID',
      `create_time` datetime DEFAULT NULL COMMENT '邮箱',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    项目中创建实体User.java
    @Data
    @TableName("user")
    public class User {
    
        @TableId(value = "id", type = IdType.AUTO)
        private Integer id;
    
        /** 姓名 */
        private String name;
    
        /** 年龄 */
        private Integer age;
    
        /** 邮箱 */
        private String email;
    
        /** 直属上级ID */
        private Integer managerId;
    
        /** 创建时间 */
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") //此注解用来接收字符串类型的参数封装成LocalDateTime类型
        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") //此注解将date类型数据转成字符串响应出去
        private LocalDateTime createTime;
    
        /** 对于数据库中没有的字段,如果我们不处理,在新增或修改的时候会出现错误,mp为我们提供了注解@TableField解决此类问题 */
        @TableField(exist = false) // exist = false标识数据库没有此字段,告诉mp映射时忽略此字段,防止出现错误,默认为true
        List<Integer> roleIds;
    }
    

    注意:对于数据库中没有的字段,如果我们不做特殊处理,我们在操作数据库时MP会给我们自动进行映射,但是因为数据库中并没有这个字段,这样就会报错:

    org.springframework.jdbc.BadSqlGrammarException: 
    ### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Unknown column 'role_ids' in 'field list'
    

    针对这种情形,我们可以使用MP提供的注解@TableField(exist = false)来表明某个字段不是数据库的字段,其中exist表示是否存在,默认为true

    创建Mapper,继承自MP给我提供的BaseMapper
    package com.tp.demo.mp.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.tp.demo.mp.entity.User;
    
    /**
     * FileName: UserMapper
     * Author:   TP
     * Description: 用户服务Mapper
     */
    public interface UserMapper extends BaseMapper<User> {
    
    }
    

    接下来就可以测试啦,实际开发中我们应该写Service,但是这里为了方便,就不写了

    常用增删改查

    新增:
    package com.tp.demo.mp;
    
    import com.tp.demo.mp.entity.User;
    import com.tp.demo.mp.mapper.UserMapper;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.time.LocalDateTime;
    
    /**
     * FileName: MybatisPlusInsertTests
     * Author:   TP
     * Description:
     */
    @SpringBootTest
    public class MybatisPlusInsertTests {
    
        @Autowired
        private UserMapper userMapper;
    
        /**
         * 插入1条数据,mp为我们提供了insert(T entity)方法
         * 该方法插入一条记录,返回影响行数
         * <p>
         * 注意⚠️:MP的默认策略为:如果实体的某个属性为null,那么新增和修改时,会忽略null值字段
         */
        @Test
        void testInsert() {
            User user = new User();
            user.setName("向东");
            user.setAge(58);
            user.setManagerId(2);
            user.setEmail("xb@163.com");
            user.setCreateTime(LocalDateTime.now());
            int rows = userMapper.insert(user);
            System.out.println("影响记录数:" + rows);
            System.out.println("新记录的主键ID:" + user.getId());
        }
    }
    

    MP为我们提供了insert(T entity)方法,该方法插入一条记录,返回影响行数,MP的默认策略为:如果实体的某个属性为null,那么新增和修改时,会忽略null值字段,如果你想获取新增的实体的ID,可以直接调用实体的getId方法获取。

    查询
    package com.tp.demo.mp;
    
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.core.toolkit.Wrappers;
    import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
    import com.tp.demo.mp.entity.User;
    import com.tp.demo.mp.mapper.UserMapper;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * FileName: MybatisPlusSelectTests
     * Author:   TP
     * Description: 查询类测试
     */
    @SpringBootTest
    class MybatisPlusSelectTests {
    
        @Autowired
        private UserMapper userMapper;
    
        // ========================= 非条件构造器查询 =========================
    
        /**
         * SELECT id,name,age,email,manager_id,create_time FROM user
         */
        @Test
        void testSelectList() {
            List<User> users = userMapper.selectList(null);
            users.forEach(System.out::println);
        }
    
        /**
         * SELECT id,name,age,email,manager_id,create_time FROM user WHERE id=?
         */
        @Test
        void testSelectById() {
            User user = userMapper.selectById(1);
            System.out.println(user);
        }
    
        /**
         * SELECT id,name,age,email,manager_id,create_time FROM user WHERE id IN ( ? , ? )
         */
        @Test
        void testSelectBatchIds() {
            List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 3));
            users.forEach(System.out::println);
        }
    
        /**
         * SELECT id,name,age,email,manager_id,create_time FROM user WHERE manager_id = ? AND name = ?
         */
        @Test
        void testSelectByMap() {
            Map<String, Object> queryMap = new HashMap<>();
            queryMap.put("name", "向北");
            queryMap.put("manager_id", 2); // 注意map的key为表的字段名,value为要查的字段值
            List<User> users = userMapper.selectByMap(queryMap);
            users.forEach(System.out::println);
        }
    
        /**
         * Map查询,查询条件值为null的不会被忽略
         * ==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE manager_id = ? AND name = ? AND email IS NULL
         * ==> Parameters: 2(Integer), 向北(String)
         */
        @Test
        void testSelectByMap2() {
            Map<String, Object> queryMap = new HashMap<>();
            queryMap.put("name", "向北");
            queryMap.put("manager_id", 2); // 注意map的key为表的字段名,value为要查的字段值
            queryMap.put("email", null);
            List<User> users = userMapper.selectByMap(queryMap);
            users.forEach(System.out::println);
        }
    
        // ========================= Wrapper条件构造器查询 =========================
    
        /**
         * 通过条件构造器查询
         * 名字为"张三",邮箱包含163,并且年龄<40
         * Preparing:  SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name = ? AND email LIKE ? AND age < ?)
         * Parameters: 张三(String), %163%(String), 40(Integer)
         */
        @Test
        void testSelectByWrapper() {
            // MP提供了2种创建QueryWrapper的方法:
            // QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            QueryWrapper<User> queryWrapper = Wrappers.query();
            queryWrapper.eq("name", "张三").like("email", "163").lt("age", 40);
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
        /**
         * 名字中包含"雨",并且年龄大于等于20且小于等于40,并且email不为空
         * Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
         * Parameters: %雨%(String), 20(Integer), 40(Integer)
         */
        @Test
        void testSelectByWrapper2() {
            // MP提供了2种创建QueryWrapper的方法:
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.like("name", "雨").between("age", 20, 40).isNotNull("email");
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
        /**
         * 名字为王姓或者年龄大于等于25,按照年龄降序排列,年龄相同时按照id升序排列
         * ==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ? OR age >= ?) ORDER BY age DESC,id ASC
         * ==> Parameters: 王%(String), 25(Integer)
         */
        @Test
        void testSelectByWrapper3() {
            // MP提供了2种创建QueryWrapper的方法:
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.likeRight("name", "王").or().ge("age", 25).orderByDesc("age").orderByAsc("id");
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
        /**
         * 名字为王姓,并且(年龄<40或邮箱为空)
         * ==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ? AND (age < ? OR email IS NOT NULL))
         * ==> Parameters: 王%(String), 40(Integer)
         */
        @Test
        void testSelectByWrapper4() {
            // MP提供了2种创建QueryWrapper的方法:
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.likeRight("name", "王").and(qw -> qw.lt("age", 40).or().isNotNull("email"));
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
        /**
         * 字为王姓,或者(年龄<40并且年龄>20并且邮箱不为空)
         * ==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ? OR (age < ? AND age > ? AND email IS NOT NULL))
         * ==> Parameters: 王%(String), 40(Integer), 20(Integer)
         */
        @Test
        void testSelectByWrapper5() {
            // MP提供了2种创建QueryWrapper的方法:
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.likeRight("name", "王").
                    or(qw -> qw.lt("age", 40).gt("age", 20).isNotNull("email"));
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
        /**
         * (年龄<40或者邮箱不为空)并且姓名为王姓
         * ==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE ((age < ? OR email IS NOT NULL) AND name LIKE ?)
         * ==> Parameters: 40(Integer), 王%(String)
         */
        @Test
        void testSelectByWrapper7() {
            // MP提供了2种创建QueryWrapper的方法:
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.nested(wp -> wp.lt("age", 40).or().isNotNull("email")).likeRight("name", "王");
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
        /**
         * 年龄在(31,32,34,45)中的
         * ==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (age IN (?,?,?,?))
         * ==> Parameters: 31(Integer), 32(Integer), 34(Integer), 35(Integer)
         */
        @Test
        void testSelectByWrapper8() {
            // MP提供了2种创建QueryWrapper的方法:
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("age", Arrays.asList(31, 32, 34, 35));
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
        /**
         * 返回满足条件的其中一条记录即可
         * ==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (age IN (?,?,?,?)) limit 1
         * ==> Parameters: 31(Integer), 32(Integer), 34(Integer), 35(Integer)
         */
        @Test
        void testSelectByWrapper9() {
            // MP提供了2种创建QueryWrapper的方法:
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("age", Arrays.asList(31, 32, 34, 35)).last("limit 1"); // last会无视优化,直接在sql后面拼接传入的语句
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
        /**
         * 默认MP会查询实体全部字段,如果我们只想查询指定字段怎么办呢?
         * 查询指定列方式一:指定要查询的字段
         * ==>  Preparing: SELECT id,name,age FROM user WHERE (age < ?)
         * ==> Parameters: 40(Integer)
         */
        @Test
        void testSelectByWrapper10() {
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("id", "name", "age").lt("age", 40);
            // .select(String... columns)可以放在前面,也可以放在后面,例如下面注释内容
            // queryWrapper.lt("age", 40).select("id", "name", "age");
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
        /**
         * 默认MP会查询实体全部字段,如果我们只想查询指定字段怎么办呢?
         * 查询指定列方式二:动态指定要查询的字段,更有利于查询实体类中多个字段,不想像方式一那样一个一个写的情形
         * ==>  Preparing: SELECT id,name,age,manager_id FROM user
         */
        @Test
        void testSelectByWrapper11() {
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            // 排除create_time和email字段,即不查询create_time和email字段
            queryWrapper.select(User.class, info -> !info.getColumn().equals("create_time") && !info.getColumn().equals("email"));
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
        /**
         * 关于condition
         * 在QueryWrapper的各个查询方法中,一般都会有重载的方法,例如like
         * <p>
         * default Children like(R column, Object val) {
         * return this.like(true, column, val);
         * }
         * <p>
         * Children like(boolean condition, R column, Object val);
         * <p>
         * 其中有个重载的方法,前面需要传一个boolean类型的condition,它的含义是:如果  condition的值为true时,则添加后面的查询条件
         * 例如我们做页面的列表,用户可输入多个查询条件,有值的就添加上查询条件
         */
        @Test
        void testSelectByWrapper12() {
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            boolean condition = (int) (Math.random() * 100) % 2 == 1;
            System.out.println(condition);
            queryWrapper
                    .lt("age", 40)
                    .eq(condition, "name", "张三"); //如果condition为false时,不会添加查询条件:and name = "张三"
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
    
        /**
         * 我们可以通过一个实体构造一个queryWrapper,MP默认会将实体属性中值不为空的作为查询条件,用and连接生成sql
         * ==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE name=? AND age=?
         * ==> Parameters: 向东(String), 58(Integer)
         */
        @Test
        void testSelectByEntity() {
            User queryUser = new User();
            queryUser.setName("向东");
            queryUser.setAge(58);
            QueryWrapper<User> queryWrapper = new QueryWrapper<>(queryUser);
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
    
        /**
         * 调用queryWrapper.allEq(params)      时,params中的null值会被翻译成:字段名 is null
         * 调用queryWrapper.allEq(params,false)时,params中的null值会被忽略
         */
        @Test
        void testAllEq() {
            // name = "向东" and age is null
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            Map<String, Object> params = new HashMap<>();
            params.put("name", "向东");
            params.put("age", null);
            queryWrapper.allEq(params);
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
    
            // name = "向东"
            QueryWrapper<User> queryWrapper2 = new QueryWrapper<>();
            Map<String, Object> params2 = new HashMap<>();
            params2.put("name", "向东");
            params2.put("age", null);
            queryWrapper2.allEq(params2, false);
            List<User> users2 = userMapper.selectList(queryWrapper2);
            users2.forEach(System.out::println);
        }
    
        /**
         * 查询返回一个map,map的key为数据库中的字段
         * 应用场景1:当我们查询的字段不是所有字段,只是部分字段,如果我们用实体封装,那么实体中中未查询的字段就为空或者默认值,不优雅,这个时候可以用map接收指定查询的字段
         * 应用场景2:当我们需要将数据库中的字段进行转换,或者使用函数时,这时候无法用实体封装查询结果,我们可以选择使用map
         */
        @Test
        void testSelectMaps() {
            // 应用场景1
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("name", "向东");
            queryWrapper.select("name", "age"); // 只查询部分字段
            List<Map<String, Object>> result = userMapper.selectMaps(queryWrapper);
            result.forEach(System.out::println);
    
            //应用场景2
            QueryWrapper<User> queryWrapper2 = new QueryWrapper<>();
            queryWrapper2
                    .select("avg(age) avg_age", "min(age) min_age", "max(age) max_age", "manager_id") // 计算查询
                    .groupBy("manager_id").having("sum(age)<{0}", 50);
            List<Map<String, Object>> result2 = userMapper.selectMaps(queryWrapper2);
            result2.forEach(System.out::println);
        }
    
        /**
         * 根据Wrapper查询,查询全部记录
         * 注意:只返回结果第一个字段的值
         */
        @Test
        void testSelectObjects() {
            // 应用场景1
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("id", "name").lt("age", 60);
            List<Object> objects = userMapper.selectObjs(queryWrapper); // 只会返回id,不会返回name  {1,2,3,4,5,6,7,8}
            objects.forEach(System.out::println);
    
        }
    
        /**
         * 根据查询条件进行统计总记录数
         */
        @Test
        void testSelectCount() {
            // 应用场景1
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.lt("age", 60);
            Integer count = userMapper.selectCount(queryWrapper);
            System.out.println(count);
    
        }
    
        /**
         * 查询1条结果,结果必须为1条或0条
         * 如果数据库存在多条会报错
         */
        @Test
        void testSelectOne() {
            // 应用场景1
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("id", 1);
            User user = userMapper.selectOne(queryWrapper);
            System.out.println(user);
        }
    
        // ========================= Lambda条件构造器查询 =========================
    
        /**
         * Lambda条件构造器查询能有效防止我们手写数据库字段写错问题
         */
        @Test
        void testSelectLambda1() {
            // 创建Lambda条件构造器的方式有3种:
            LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            LambdaQueryWrapper<User> lambdaQueryWrapper1 = Wrappers.lambdaQuery();
            LambdaQueryWrapper lambdaQueryWrapper2 = new QueryWrapper<User>().lambda();
            // User::getNamed代表要查询name这个列,lambdaQueryWrapper的好处是避免手写要查询字段字符串,如果手写的也数据库不一致造成报错问题
            lambdaQueryWrapper.eq(User::getName, "向东").lt(User::getAge, 80);
            List<User> users = userMapper.selectList(lambdaQueryWrapper);
            users.forEach(System.out::println);
        }
    
        @Test
        void testSelectLambda2() {
            // 创建Lambda条件构造器的方式有3种:
            LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            LambdaQueryWrapper<User> lambdaQueryWrapper1 = Wrappers.lambdaQuery();
            LambdaQueryWrapper lambdaQueryWrapper2 = new QueryWrapper<User>().lambda();
            // where name like %王% and (age < 80 or email is not null)
            lambdaQueryWrapper.likeRight(User::getName, "王").and(lqw -> lqw.lt(User::getAge, 40).or().isNotNull(User::getEmail));
            List<User> users = userMapper.selectList(lambdaQueryWrapper);
            users.forEach(System.out::println);
        }
    
        /**
         * LambdaQueryChainWrapper,这个可以再次简化写法,可以直接调用.list() 或者 .one() 返回查询结果
         */
        @Test
        void testSelectLambdaQueryChainWrapper() {
            // 创建Lambda条件构造器的方式有3种:
            LambdaQueryChainWrapper<User> lambdaQueryChainWrapper = new LambdaQueryChainWrapper<>(userMapper);
            List<User> users = lambdaQueryChainWrapper
                    .likeRight(User::getName, "王")
                    .and(lqw -> lqw.lt(User::getAge, 40).or().isNotNull(User::getEmail))
                    .list(); // 可以直接调用.list() 或者 .one() 返回查询结果
            users.forEach(System.out::println);
        }
    }
    
    修改
    package com.tp.demo.mp;
    
    import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
    import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
    import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
    import com.tp.demo.mp.entity.User;
    import com.tp.demo.mp.mapper.UserMapper;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    /**
     * FileName: MybatisPlusUpdateTests
     * Author:   TP
     * Description:
     */
    @SpringBootTest
    class MybatisPlusUpdateTests {
    
        @Autowired
        private UserMapper userMapper;
    
        /**
         * UpdateById
         * 根据主键ID修改实体信息的方法
         * 此更新会忽略实体null值,不会更新实体中属性值为null对应的字段
         */
        @Test
        void testUpdateById() {
            User user = new User();
            user.setId(8);
            user.setEmail("xd@163.com");
            userMapper.updateById(user);
        }
    
        /**
         * 利用UpdateWrapper更新实体>>>>空参构造器:UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
         * UpdateWrapper的条件会出现在where条件中
         * 实体不为空的信息是要更新的字段
         */
        @Test
        void testUpdateByWrapper() {
            // UpdateWrapper的条件会出现在where条件中
            UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("name", "李艺伟");
            updateWrapper.eq("age", 28);
    
            // 实体不为空的信息是要更新的字段
            User user = new User();
            user.setEmail("lyw@126.com");
            user.setManagerId(1);
    
            // 返回影响行数
            int rows = userMapper.update(user, updateWrapper);
            System.out.println("影响行数:" + rows);
    
        }
    
        /**
         * 利用UpdateWrapper更新实体>>>>带参构造器:UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(whereUser);
         * 这时候updateWrapper中会将whereUser这个实体中不为空的属性设置为where查询条件
         * 注意:这个时候whereUser实体的查询条件和后续updateWrapper调用查询方法时指定的查询条件会同时生效,如果存在相同查询条件,查询条件会出现2次
         */
        @Test
        void testUpdateByWrapper2() {
            // 通过实体构造查询条件
            User whereUser = new User();
            whereUser.setName("李艺伟");
            whereUser.setAge(28);
            UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(whereUser);
            // updateWrapper.eq("manager_id", 1); // 可以继续添加查询条件
    
            // 实体不为空的信息是要更新的字段
            User user = new User();
            user.setEmail("lyw@qq.com");
            user.setManagerId(2);
    
            // 返回影响行数
            int rows = userMapper.update(user, updateWrapper);
            System.out.println("影响行数:" + rows);
    
        }
    
        /**
         * 利用UpdateWrapper更新实体>>>>带参构造器:UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(whereUser);
         * 如果我们更新的字段很少,例如实体中我们只更新1、2个字段,如果像上面的更新还需要创建一个对象,这样有点不优雅
         * 又或者我们的需求是想把某个字段设置为null
         * 这时候我们可以使用UpdateWrapper的set方法,指定设置数据库表中具体哪个字段设置为什么值
         */
        @Test
        void testUpdateByWrapper3() {
            // 通过实体构造查询条件
            User whereUser = new User();
            whereUser.setName("李艺伟");
            whereUser.setAge(28);
            UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(whereUser);
            updateWrapper.set("age", 29).set("email", null);
    
            // 返回影响行数
            int rows = userMapper.update(null, updateWrapper);
            System.out.println("影响行数:" + rows);
    
        }
    
        /**
         * UpdateWrapper同样支持Lambda形式,用法类似LambdaQueryWrapper
         */
        @Test
        void testUpdateByWrapperLambda() {
            // 构造LambdaUpdateWrapper
            LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.eq(User::getName, "李艺伟").set(User::getAge, 30).set(User::getEmail, "lyw@163.com");
            // 返回影响行数
            int rows = userMapper.update(null, lambdaUpdateWrapper);
            System.out.println("影响行数:" + rows);
        }
    
        /**
         * 同理,UpdateWrapper同样支持LambdaChain形式
         * 用法类似LambdaQueryChainWrapper
         * 但其返回值不是影响行数,而是boolean值,标识更新成功或失败
         */
        @Test
        void testUpdateByWrapperLambdaChain() {
            // 构造LambdaUpdateWrapper
            LambdaUpdateChainWrapper<User> chainWrapper = new LambdaUpdateChainWrapper<>(userMapper);
            boolean result = chainWrapper
                    .eq(User::getName, "李艺伟") // 设置查询条件
                    .set(User::getAge, 31).set(User::getEmail, "lyw@chain.com") //设置要更新的内容
                    .update(); //需要调用update(),执行更新
            System.out.println("更新是否成功:" + result);
    
        }
    }
    
    删除
    package com.tp.demo.mp;
    
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.core.toolkit.Wrappers;
    import com.tp.demo.mp.entity.User;
    import com.tp.demo.mp.mapper.UserMapper;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * FileName: MybatisPlusDeleteTests
     * Author:   TP
     * Description:
     */
    @SpringBootTest
    class MybatisPlusDeleteTests {
    
        @Autowired
        private UserMapper userMapper;
    
        /**
         * 根据ID单个删除
         */
        @Test
        void testDeleteById() {
            int rows = userMapper.deleteById(8);
            System.out.println("影响记录数:" + rows);
        }
    
        /**
         * 根据ID批量删除
         */
        @Test
        void testDeleteBatchIds() {
            int rows = userMapper.deleteBatchIds(Arrays.asList(9, 10));
            System.out.println("影响记录数:" + rows);
        }
    
        /**
         * 根据Map,map中的元素会作为查询条件且等值and连接
         */
        @Test
        void testDeleteByMap() {
            Map<String, Object> map = new HashMap<>();
            map.put("name", "向东");
            map.put("age", 31);
            map.put("manager_id", null);
            int rows = userMapper.deleteByMap(map);
            System.out.println("影响记录数:" + rows);
        }
    
        /**
         * 根据QueryWrapper条件构造器删除
         */
        @Test
        void testDeleteByWrapper() {
            QueryWrapper<User> queryWrapper = Wrappers.query();
            queryWrapper.eq("name", "向东");
            queryWrapper.eq("age", "31");
            int rows = userMapper.delete(queryWrapper);
            System.out.println("影响记录数:" + rows);
        }
    
        /**
         * 根据QueryWrapper条件构造器,通过指定一个实体删除
         */
        @Test
        void testDeleteByWrapper2() {
            User user = new User();
            user.setName("向东");
            user.setAge(31);
            QueryWrapper<User> queryWrapper = Wrappers.query(user);
            int rows = userMapper.delete(queryWrapper);
            System.out.println("影响记录数:" + rows);
        }
    
        /**
         * 根据LambdaQueryWrapper条件构造器删除
         */
        @Test
        void testDeleteByLambdaQueryWrapper() {
            LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();
            // DELETE FROM user WHERE (name = ? OR age >= ?)
            lambdaQueryWrapper.eq(User::getName, "向东").or().ge(User::getAge, 60);
            int rows = userMapper.delete(lambdaQueryWrapper);
            System.out.println("影响记录数:" + rows);
        }
    
        /**
         * 根据LambdaQueryWrapper条件构造器,通过指定一个实体删除
         */
        @Test
        void testDeleteByLambdaQueryWrapper2() {
            User user = new User();
            user.setName("向东");
            user.setAge(50);
            LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery(user);
            int rows = userMapper.delete(lambdaQueryWrapper);
            System.out.println("影响记录数:" + rows);
        }
    }
    

    Mybatis-Plus分页

    Mybatis-Plus为我们提供了非常方便的分页插件,用法:

    package com.tp.demo.mp.config;
    
    import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * FileName: MybatisPlusPageConfig
     * Author:   TP
     * Description: 使用mybatisPlus的分页插件
     * 只需要提供一个PaginationInnerInterceptor交给Spring管理即可
     */
    @Configuration
    public class MybatisPlusPageConfig {
    
        @Bean
        public PaginationInnerInterceptor paginationInnerInterceptor(){
            return new PaginationInnerInterceptor();
        }
    }
    

    测试:

    package com.tp.demo.mp;
    
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.tp.demo.mp.entity.User;
    import com.tp.demo.mp.mapper.UserMapper;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.List;
    import java.util.Map;
    
    /**
     * FileName: MybatisPlusPageTests
     * Author:   TP
     * Description: mybatisPlus分页测试
     */
    @SpringBootTest
    class MybatisPlusPageTests {
    
        @Autowired
        private UserMapper userMapper;
    
        /**
         * 分页,结果采用实体封装
         */
        @Test
        void testPage1() {
            Page<User> userPage = new Page<>(1, 10); //当前页为第1页,每页显示10条
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.lt("age", 80);
            Page<User> pageResult = userMapper.selectPage(userPage, queryWrapper);
            System.out.println("总页数:" + pageResult.getPages());
            System.out.println("总记录数:" + pageResult.getTotal());
            List<User> users = pageResult.getRecords();
            users.forEach(System.out::println);
        }
    
        /**
         * 分页,结果采用Map封装,key为列名或者列别名,value为值
         */
        @Test
        void testPage2() {
            Page<Map<String, Object>> userPage = new Page<>(1, 10); //当前页为第1页,每页显示10条
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.lt("age", 80).select("name", "age");
            Page<Map<String, Object>> pageResult = userMapper.selectMapsPage(userPage, queryWrapper);
            System.out.println("总页数:" + pageResult.getPages());
            System.out.println("总记录数:" + pageResult.getTotal());
            List<Map<String, Object>> users = pageResult.getRecords();
            users.forEach(System.out::println);
        }
    }
    

    相关文章

      网友评论

        本文标题:Mybatis-Plus极速入门

        本文链接:https://www.haomeiwen.com/subject/kgevvktx.html