• mybatis-plus学习笔记


    1 简介

    MyBatis-Plus是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。MyBatis-Plus提供了通用的mapper和service,可以在不编写任何SQL语句的情况下,快速的实现对单表的CRUD、批量、逻辑删除、分页等操作。

    2 初始化项目

    2.1引入pom

    <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starterartifactId>
            dependency>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
    
            
            <dependency>
                <groupId>com.baomidougroupId>
                <artifactId>mybatis-plus-boot-starterartifactId>
                <version>3.5.1version>
            dependency>
            
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <optional>trueoptional>
            dependency>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <scope>runtimescope>
            dependency>
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    2.2 引入lombok插件

    在这里插入图片描述

    2.3 配置信息

    spring:
    # 配置数据源信息
      datasource:
    # 配置数据源类型(spring默认的数据源)
        type: com.zaxxer.hikari.HikariDataSource
    # 配置连接数据库信息(配置驱动类,版本为8)
        driver-class-name: com.mysql.cj.jdbc.Driver
    #mysql8版本的写法
        url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
        username: root
        password: yuan159951.
    
    # mysql5版本的写法
    # driver-class-name: com.mysql.jdbc.Driver
    # url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.4 创建实体类

    import lombok.Data;
    
    @Data //lombok注解
    public class User {
            private Long id;
            private String name;
            private Integer age;
            private String email;   
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.5 创建mapper

    import com.yunfeng.mybatisplus.pojo.User;
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    
    public interface UserMapper extends BaseMapper<User> {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.6 配置注解MapperScan

    @SpringBootApplication
    //扫描mapper接口所在的包
    @MapperScan("com.yunfeng.mybatisplus.mapper")
    public class MybatisplusApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(MybatisplusApplication.class, args);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.7 编写测试类

    import com.yunfeng.mybatisplus.mapper.UserMapper;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    public class MybatisPlusTest {
    
        @Autowired
        private UserMapper userMapper;
    
        @Test
        public void testSelectList(){
            //selectList()根据MP内置的条件构造器查询一个list集合,null表示没有条件,即查询所有
            userMapper.selectList(null).forEach(System.out::println);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.8 配置MyBatis日志

    # 配置MyBatis日志
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    
    • 1
    • 2
    • 3
    • 4

    3 测试基本的CRUD

    3.1 新增

    @Test
        public void testInsert(){
            User user = new User();
            user.setName("张三");
            user.setAge(18);
            user.setEmail("302976975@qq.com");
            int row = userMapper.insert(user);
            System.out.println("row = " + row);
            System.out.println(user.getId());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.2 查询

        @Test
        public void testSelectById(){
    //        User user = userMapper.selectById(1L);
    //        System.out.println(user);
    //        List longs = Arrays.asList(1l, 2l, 3l);
    //        List users = userMapper.selectBatchIds(longs);
    //        System.out.println("users = " + users);
    //        Map map = new HashMap<>();
    //        map.put("name","jack");
    //        map.put("age",20);
    //        List users = userMapper.selectByMap(map);
    //        System.out.println("users = " + users);
            List<User> users = userMapper.selectList(null);
            System.out.println("users = " + users);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3.3 修改

    @Test
        public void testUpdateById(){
            User user = new User();
            user.setId(4L);
            user.setName("李四");
            int result = userMapper.updateById(user);
            System.out.println("受影响行数:"+result);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.4 删除

        @Test
        public void testDeleteById(){
    //        int result = userMapper.deleteById(1595594324846141442L);
    //        System.out.println("受影响行数:"+result);
    //        Map,Object> map = new HashMap<>();
    //        map.put("name","张三");
    //        map.put("age",18);
    //        userMapper.deleteByMap(map);
            List> longs = Arrays.asList(1l, 2l, 3l);
            int rows = userMapper.deleteBatchIds(longs);
            System.out.println("rows = " + rows);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4 自定义动态sql

    • 默认位置可以不写!
      在这里插入图片描述
    • 新增mybatis模板文件
      在这里插入图片描述
    • 官方模板文件
    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.yunfeng.mybatisplus.mapper.UserMapper">
    
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • UserMapper接口代码
    Map<String,Object> selectMapById(Long id);
    
    • 1
    • UserMapper.xml代码
    <select id="selectMapById" resultType="map">
            select * from user where id = #{id}
        select>
    
    • 1
    • 2
    • 3
    • 测试类
    Map<String, Object> map = userMapper.selectMapById(1l);
            System.out.println("map = " + map);
    
    • 1
    • 2

    5 Service 层使用mybatis-plus方法

    5.1 service层代码

    • 接口
    public interface UserService  extends IService<User> {
    }
    
    • 1
    • 2
    • 实现类
    @Service
    public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService{
    
    }
    
    • 1
    • 2
    • 3
    • 4

    5.2 测试查询总记录数

    @Test
        public void testGetCount(){
            long count = userService.count();
            System.out.println("count = " + count);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5.3 测试批量新增

    	@Test
        public void testSaveBatch(){
    // SQL长度有限制,海量数据插入单条SQL无法实行,
    // 因此MP将批量插入放在了通用Service中实现,而不是通用Mapper
            ArrayList<User> users = new ArrayList<>();
            for (int i = 0; i < 5; i++) {
                User user = new User();
                user.setName("ybc" + i);
                user.setAge(20 + i);
                users.add(user);
            }
    //SQL:INSERT INTO t_user ( username, age ) VALUES ( ?, ? )
            boolean bool = userService.saveBatch(users);
            System.out.println("bool = " + bool);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6 id不是用雪花算法,自己定义

    @Data //lombok注解
    @TableName("user")
    public class User {
    
    //IdType.AUTO就是自增
            @TableId(value = "id",type = IdType.AUTO)
            private Long id;
            @TableField("name")
            private String name;
            private Integer age;
            private String email;
    		//逻辑删除
            @TableLogic
            private Integer isDeleted;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 配置方法
    # 配置MyBatis
    mybatis-plus:
      configuration:
        # 日志信息
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      global-config:
        db-config:
          # 配置MyBatis-Plus的主键策略
          id-type: auto
        # 配置MyBatis-Plus操作表的默认前缀
    #      table-prefix:
      # 配置类型别名所对应的包
      type-aliases-package: com.yunfeng.mybatisplus.pojo
      # 配置扫描通用枚举
      type-enums-package: com.yunfeng.mybatisplus.enums
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    7 雪花算法

    雪花算法是由Twitter公布的分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的
    主键的有序性。

    • 和时间有关。
    • ①核心思想:
      长度共64bit(一个long型)。
      首先是一个符号位,1bit标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负
      数是1,所以id一般是正数,最高位是0。
      41bit时间截(毫秒级),存储的是时间截的差值(当前时间截 - 开始时间截),结果约等于69.73年。
      10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID,可以部署在1024个节点)。
      12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID)。
    • ②优点:整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞,并且效率较高。
      在这里插入图片描述

    8 wapper条件构造器

    8.1 QueryWrapper(查询、删除、修改)

    • 查询
    	@Test
        public void test01(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.like("name","a")
                    .between("age",20,30)
                    .isNotNull("email");
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 查询排序
    	@Test
        public void test02(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.orderByDesc("age")
                    .orderByAsc("id");
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 删除
    	@Test
        public void test03(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.isNull("email");
            int row = userMapper.delete(queryWrapper);
            System.out.println("row = " + row);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 条件修改
    	@Test
        public void test04(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.gt("age",20)
                    .like("name","a")
                    .or()
                    .isNull("email");
            User user = new User();
            user.setName("张三");
            int rows = userMapper.update(user, queryWrapper);
            System.out.println("rows = " + rows);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • lambda中的条件优先执行
    @Test
        public void test05(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            //lambda中的条件优先执行
            queryWrapper.like("name","a")
                    .and(i -> i.gt("age",20).or().isNull("email"));
            User user = new User();
            user.setName("李四");
            int rows = userMapper.update(user, queryWrapper);
            System.out.println("rows = " + rows);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 查询部分字段
    //查询部分字段
        @Test
        public void test06(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("name","age");
            List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
            maps.forEach(System.out::println);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 子查询
    // 子查询
        @Test
        public void test07(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.inSql("age","select age from user where age < 20");
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    8.2 UpdateWrapper

    • UpdateWrapper修改不需要new实体类
    @Test
        public void test08(){
            UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
            updateWrapper.like("name","a")
                    .and( i -> i.gt("age",20).or().isNull("email"));
            updateWrapper.set("name","王五");
            int rows = userMapper.update(null, updateWrapper);
            System.out.println("rows = " + rows);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 条件组装
    @Test
        public void test10(){
            String name = "";
            Integer ageBegin = 20;
            Integer ageEnd = 30;
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.like(StringUtils.isNotBlank(name),"name",name)
                    .ge(ageBegin != null,"age",ageBegin)
                    .gt(ageEnd != null,"age",ageEnd);
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    8.3 LambdaQueryWrapper

    @Test
        public void test11(){
            String name = "";
            Integer ageBegin = 20;
            Integer ageEnd = 30;
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.like(StringUtils.isNotBlank(name),User::getName,name)
                    .ge(ageBegin != null,User::getAge,ageBegin)
                    .gt(ageEnd != null,User::getAge,ageEnd);
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    8.4 LambdaUpdateWrapper

    @Test
        public void test12(){
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.like(User::getName,"a")
                    .and( i -> i.gt(User::getAge,20).or().isNull(User::getEmail));
            updateWrapper.set(User::getName,"赵六");
            int rows = userMapper.update(null, updateWrapper);
            System.out.println("rows = " + rows);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    9 插件

    9.1 分页插件

    • 写配置类
    import com.baomidou.mybatisplus.annotation.DbType;
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    //扫描mapper接口所在的包
    @MapperScan("com.atguigu.mybatisplus.mapper")
    public class MyBatisPlusConfig {
    
        //分页插件
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor(){
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            return interceptor;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 测试
    @Test
        public void testPage(){
            Page<User> page = new Page<>(2,3);
            userMapper.selectPage(page, null);
            System.out.println("page = " + page);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    9.2 乐观锁和悲观锁

    • 添加@Version注解
    @Data
    public class Product {
    private Long id;
    private String name;
    private Integer price;
    @Version
    private Integer version;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 添加插件
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
    	MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    	//添加分页插件
    	interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    	//添加乐观锁插件
    	interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    	return interceptor;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    10 代码生成器

    10.1引入以依赖

    
            <dependency>
                <groupId>com.baomidougroupId>
                <artifactId>mybatis-plus-generatorartifactId>
                <version>3.5.1version>
            dependency>
    
            <dependency>
                <groupId>org.freemarkergroupId>
                <artifactId>freemarkerartifactId>
                <version>2.3.31version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    10.2 生成代码

    public static void main(String[] args) {
            FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/mybatis_plus?characterEncoding=utf-8&userSSL=false", "root", "yuan159951.")
                    .globalConfig(builder -> {
                        builder.author("logic") // 设置作者
                                //.enableSwagger() // 开启 swagger 模式
                                .fileOverride() // 覆盖已生成文件
                                .outputDir("D://mybatis_plus"); // 指定输出目录
                    })
                    .packageConfig(builder -> {
                                 builder.parent("com.yunfeng") // 设置父包名
                                        .moduleName("mybatisplus") // 设置父包模块名
                                        .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus")); // 设置mapperXml生成路径
                    })
                    .strategyConfig(builder -> {
                                builder.addInclude("user") // 设置需要生成的表名
                                       .addTablePrefix("t_", "c_"); // 设置过滤表前缀
                    })
                    .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker 引擎模板,默认的是Velocity引擎模板
                    .execute();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  • 相关阅读:
    【开源】基于Vue.js的森林火灾预警系统的设计和实现
    团建游戏------飞人降落
    物理学家用AI改写教科书!质子中发现新的夸克,可能性高达99.7%
    Linux环境配置(云服务器)
    解锁横向招聘:创新您的人才搜索
    二十六、MySQL并发事务问题:脏读/不可重复读/幻读
    React——关于JSX
    make quick-example I: 变量语法 & 变量插值
    第26章_瑞萨MCU零基础入门系列教程之独立看门狗定时器-IWDT
    (附源码)springboot手工diy网站 毕业设计 310226
  • 原文地址:https://blog.csdn.net/weixin_43684214/article/details/128007977