Mybatis-plus >>>>>从入门到入狱_mybatisplus中的->作用是什么-程序员宅基地

技术标签: 工具搭建  mybatis  

一、什么是Mybatis-plus

Mybatis的出现 是为了简化JDBC的复杂操作,而Mybatis-plus的出现则是为了简化Mybatis的操作,它不会改变mybatis原有的东西,只会在原有的基础上增加功能,可以说,它是非入侵式的,蕴含了AOP的思想

在这里插入图片描述

二、Mybatis-plus的特点

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
  • **数据库支持:**支持市面上所有可以使用Mybatis操作CRUD的数据库

三、快速入门

  • 现有一张 User 表,其表结构如下:
id name age email
1 Jone 18 [email protected]
2 Jack 20 [email protected]
3 Tom 28 [email protected]
4 Sandy 21 [email protected]
5 Billie 24 [email protected]
DROP TABLE IF EXISTS user;

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');
  • 创建一个SpringBoot项目

  • 添加MybatisPlus启动器依赖

         <!-- mybatis-plus-启动器 -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.4.3</version>
            </dependency>
    
            <dependency>
                <groupId>com.h2database</groupId>
                <artifactId>h2</artifactId>
                <scope>runtime</scope>
            </dependency>
    
  • 编写实体类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
          
        private Long id;
        private String name;
        private Integer age;
        private String email;
    }
    
  • 编写Mapper类

@Mapper
@Repository
public interface UserMapper  extends BaseMapper<User> {
    

}
/*
		继承BaseMapper<T>类 T是一个泛型  这里填入我们的实体类
		我们就可以直接使用MybatisPlus为我们封装好的CRUD方法

*/
  • 编写数据库数据源和日志

    #数据库连接配置  mysql 8.0版本的多了时区设置 GMT%2b8就是我们东八区的时区
    spring:
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/mybatis-plus?serverTimezone=GMT%2b8
        username: root
        password: 123456
    #日志配置 默认控制台输出  这里我们使用默认的日志输出
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    
  • 测试

        @Autowired
        UserMapper userMapper;
        @Test
        void contextLoads() {
          
            List<User> users = userMapper.selectList(null);
            for (User user : users) {
          
                System.out.println(user);
            }
        }
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ioBgQVLf-1627193026466)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210724214846320.png)]

这样 我们的Mybatis-Plus环境就算搭建完成了

四、CRUD的探究

Insert

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1YnfMPGd-1627193026467)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210724215334759.png)]

查看insert的方法 只有一个 返回值是一个entity实体类对象

我们在不插入ID的情况下 进行测试看看发生什么

   //插入测试
    @Test
    public void text1(){
    
        User user = new User();
        user.setAge(18);
        user.setName("狂神");
        user.setEmail("[email protected]");
        userMapper.insert(user);
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XLVj58oH-1627193026469)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210724215545393.png)]

通过控制台输出 我们发现 它自动给我们生成了一个Long类型的数字 那么它是怎么来的呢?

原来,Mybatis-plus的insert语句中,内置了主键自增策略,当我们的ID为NULL时,它会自动给我们生成一串数字,这串数字是由雪花算法产生的,而产生的前提是ID的类型必须Long类型,雪花算法也是它的默认类型

注意:

如果我们的ID类型为其他类型。且插入的时候为NULL 运行程序就会报错

Caused by: 
org.apache.ibatis.reflection.ReflectionException: Could not set property 'id' of 'class com.llf.Pojo.User' with value '1418934148565385218' Cause: java.lang.IllegalArgumentException: argument type mismatch
    翻译:无法将long类型的值'1418934148565385218'赋给ID   
雪花算法是什么呢?

说白了 它就是一种随机生成主键的算法 它有以下特点

  • 最高位是符号位,始终为0,不可用。
  • 41位的时间序列,精确到毫秒级,41位的长度可以使用69年。时间位还有一个很重要的作用是可以根据时间进行排序。
  • 10位的机器标识,10位的长度最多支持部署1024个节点。
  • 12位的计数序列号,序列号即一系列的自增id,可以支持同一节点同一毫秒生成多个ID序号,12位的计数序列号支持每个节点每毫秒产生4096个ID序号。
其他的主键生成策略

在mybatis-plus中,除了默认的雪花算法还有许多主键生成策略

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MljLExaQ-1627193026470)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210724221108611.png)]

  • ASSIGN_ID

    Twitter的分布式自增ID算法 雪花算法 就是我们默认的主键生成策略

    形式:1418884175761063937

  • ASSIGN_UUID

    形式:6904b36e-e220-2fcf-4e00-23c3449e1e24

    随机生成UUID,UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写 优点是

    ​ 优点:性能非常高,JDK自带本地生成,无网络消耗

    ​ 缺点:(1)只保证了唯一性,趋势递增。

    ​ (2)无序,无法预测他的生成规则,不能生成递增有序的数字。

    ​ (3)mysql官方推荐主键越短越好,UUID包含32个16位进制的字母数字,每一个都很长。

    ​ (4)B+树索引的分裂。主键是包含索引的,mysql的索引是通过B+树来实现的,因为UUID是无序的,插入无序,不但会导致一些中间节点产生分裂,也会白白创造很多不饱和的节点,大大降低了数据库插入的性能。

  • AUTO

    主键自增,也是最简单的主键生成策略,但是实现的前提必须是数据库必须打开主键自增的设置

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wBsrHBOd-1627193026471)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210724221819792.png)]

  • INPUT

    自己输入 即自己Set注入

     User user = userMapper.selectById(1l);
      user.setId(2L);
    userMapper.updateById(user);
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5oKrMpqT-1627193026472)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210724223757150.png)]

  • NONE

    什么也不输入 如果这张表中没有主键,即为NULL 但基本上不会这么做。

delete

物理删除:delete 语句就是物理删除 一旦删除 就没有了
逻辑删除:通过代码设置 在查询的时候不显示 实际上数据库中还有 只是状态不同了 类似于回收站

物理删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pou1Oqly-1627193026473)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210724224449038.png)]

  • deleteById

    通过单个id删除

  • deleteBatchIds

    通过多个id同时删除

  • deleteByMap

    通过一个Map集合删除

        @Test
        public void text5(){
          
            userMapper.deleteById(1418846421555712001l);
            System.out.println("通过id删除成功");
            userMapper.deleteBatchIds(Arrays.asList(1418844779586318338l,1418844779586318337l));
            System.out.println("多个ID删除成功");
            HashMap<String, Object> map = new HashMap<>();
            map.put("id","10");
            userMapper.deleteByMap(map);
            System.out.println("通过map删除成功");
        }
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GlH6sqUi-1627193026473)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210724225510991.png)]

逻辑删除
  • 逻辑删除的本质就是通过查询不同状态 来显示数据 所以我们在数据库中增加字段deleted

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4yovj2wr-1627193026474)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210724230129680.png)]

我们设定0为正常显示 1为不显示 并设置默认值为0

  • 然后在Pojo实体类中完善字段 并添加注解
    //逻辑删除注解
    @TableLogic
    private Integer deleted;
  • 在application中进行01显示设置
mybatis-plus:
  global-config:
    db-config:
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

  • 测试
userMapper.deleteById(4);
 System.out.println("通过id删除成功");

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DJZoSAL3-1627193026475)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210724230641270.png)]

这时我们可以发现删除语句 在后台已经变成了更新语句

  • 查询

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zeFk6cTv-1627193026475)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210724230812922.png)]

通过查询 和数据库查询 我们发现这些值在数据库中依然存在 只是查询不到了 这就表明实现了逻辑删除

updete

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LI180oOJ-1627193026476)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210725092011217.png)]

更新 只有两种方法 ,一种是传入一个对象,一种是传入对象+构造器Wrapper 关于构造器 我们这里先让他为null

  • update

    传入一个对象 修改所有值 相当于普通更新 没有where条件条件(Wapper构造器可以添加条件 但这里先不用)

	@Test
    public void text8(){
    
        User user = new User();
        user.setId(1418932799022907393L);
        user.setAge(18);
        user.setName("狂");
        user.setEmail("[email protected]");
        userMapper.update(user,null);

    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YfKtMw7y-1627193026476)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210725092637244.png)]

他把所有信息都更改了

  • updateById

顾名思义 传入一个对象 通过id修改内容

  @Test
    public void text8(){
    
        User user1 = new User();
        user1.setId(11L);
        user1.setAge(1);

        // userMapper.update(user,null);
        userMapper.updateById(user1);
    }

在这里插入图片描述

自动填充

按照规范,我们在数据库设计的过程中会加入create_time、update_time,但是这些时间理论上应该是自动生成,而不是我们一个一个New Data()实现的 Mybatis-Plus就为我们完成了这个功能

  • 在数据库添加字段 create_time、update_time
  • 完善实体类,在属性create_time、update_time上添加注解
    //在插入时填充时间
    @TableField(fill = FieldFill.INSERT_UPDATE )
    private Date  createTime;
    //更新时更新时间
    @TableField(fill = FieldFill.UPDATE)
    private Date   updateTime;

  • 创建MetaObjectHandler类,进行设置
package com.llf.Handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

@Slf4j
//添加@Componment注解 表示被Spring托管
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    
    /**
     * 自动填充时间
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
    
        log.info("start insert fill ....");
        //插入时填充 create_time、update_time时间
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
    
        log.info("start update fill ....");
        //修改时 填充update_time时间
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

  • 测试

在这里插入图片描述

select

在这里插入图片描述

和删除的方法一样 就不过多叙述

五、乐观锁

什么是乐观锁?

乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回给用户错误的信息,让用户决定如何去做。

简单来说,就是 比较乐观,认为程序是不会出毛病的,如果出毛病了 就进行解决

而悲观锁与其相反,悲观锁在做任何事的时候,都会提前检查,这样虽然提高了安全性,但使效率大大降低

实现乐观锁

  • 首先在数据库添加字段 version 使其默认值为1
  • 完善实体类
//添加注解 告诉系统 这是一个乐观锁
@Version
    private  Integer version;
  • 创建config类 配置引入插件配置(全是官网原码,我们直接复制就行)
package com.llf.config;


import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

//打开事务管理 即事务回滚之类的操作
@EnableTransactionManagement
// 告诉springBoot  这是spring配置类
@Configuration
public class MybatisplusConfig {
    
    /**
    乐观锁: OptimisticLockerInnerInterceptor
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
    
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }

}

  • 测试
//乐观锁成功测试
// 所谓成功,就是对象A查询数据库后,拿到Version 在执行更新操作的时候 将拿到的version与此时数据库中对应的version进行对比,刚好一致  因此  就成功了
@Test
public void text2(){
    
    User user = userMapper.selectById(1l);
    user.setId(11L);
    user.setName("过");
    userMapper.updateById(user);
}

//乐观锁失败测试
// 所谓失败,就是一个对象A查询完数据库后,在提交更新操作之前,另一个对象B也查询了数据库,并完成了更新操作,这时数据库中的version是A查询的version+1,这显然与A查询的version不相等 所以就失败了
@Test
public void text3(){
    
    User user = userMapper.selectById(1l);
    user.setId(2L);
    user.setName("杨过");
    User user2 = userMapper.selectById(1l);
    user.setId(2L);
    user.setName("杨过");
    userMapper.updateById(user2);
    userMapper.updateById(user);
}

在这里插入图片描述

六、分页

Mybatis-plus为我们准备了比PageHelper更为方便的分页插件

  • 引入分页插件
   /**
   
     * 新的分页插件,一缓和二缓遵循mybatis的规则,
     * 需要设置 MybatisConfiguration#useDeprecatedExecutor = false
     * 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor1() {
    
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
        return interceptor;
    }

将其放在 乐观锁的config配置文件中 因为同属于MybatisPlus配置文件

  • 测试
    //分页查寻
    @Test
    public void text7(){
    
        //第1页 显示3个  第一个参数是Current  第二个参数是Size
        Page<User> page = new Page<>(1,3);
        userMapper.selectPage(page,null);
       //records  总记录
        List<User> userList = page.getRecords();
        for (User user : userList) {
    
            System.out.println(user);
        }
        long size = page.getSize();
        System.out.println("页面显示大小"+size);
        long total = page.getTotal();
        System.out.println("总数量"+total);
        long current = page.getCurrent();
        System.out.println("当前页码"+current);
        long pages = page.getPages();
        System.out.println("总页数"+pages);

    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zLLOGyBh-1627193026479)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210725101130492.png)]

和PageHelper一样 在查询之前 横切了一个count(*)的查询 来查询total

在 查询后自动添加limit 分页查询 得到结果

	总记录:records  
页面显示大小":size
总数量":total				总记录是一个集合  总数量是一个值
当前页码":current
"总页数":pages

七、条件构造器

条件构造器就好比是一个能够自动帮你拼接sql的工具,按照约定大于配置的理念,我们只需要在合适的地方填入合适的参数,条件构造器就能帮我们完成复杂查询、子查询等操作

在这里插入图片描述

https://mp.baomidou.com/guide/wrapper.html#select

官方提供了许多接口供我们使用,且每一个接口的使用、参数说明都讲的很清楚

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FEpBL3DB-1627193026480)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210725113858981.png)]

  • 测试

        @Test
        public void test1(){
          
            /*
            模糊查询  查询名字里有狂字的所有人
            查询操作 就创建QueryWrapper<>()
            对应的 什么操作 就创建什么操作的Wrapper
             */
            QueryWrapper<User> wrapper = new QueryWrapper<>();
           wrapper.like("name","狂");
           //如果查询一个人 就使用selectOne() 这样效率更快
            List<Object> list = userMapper.selectObjs(wrapper);
            for (Object o : list) {
          
                System.out.println(o);
            }
    
        }
        @Test
        void test2(){
          
            //查询eamil以T开头的人
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            //以xxx开头 就是xx%  也就是likeRight
            //以xxx结尾 就是%xxx  也就是likeLeft
            wrapper.likeRight("email","t");
            List<Object> list = userMapper.selectObjs(wrapper);
            for (Object o : list) {
          
                System.out.println(o);
        }
    }
        @Test
        void test3(){
          
            //查询名字不为空的人
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.isNotNull("name");
            List<Object> objects = userMapper.selectObjs(wrapper);
            for (Object object : objects) {
          
                System.out.println(object);
            }
        }
    

更多的例子 可以参考官方例子

八、代码生成器

代码生成器 也就是我们常说的逆向工程 他可以帮助我们自动生成底层的代码框架。Pojo、Mapper、service、Controller

且支持自动生成Swagger2API注解 乐观锁、自动填充等等

  • 导入依赖

MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖

<!-- 代码生成器-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.1</version>
</dependency>
<!-- 引擎模板-->
<!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity-engine-core -->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.3</version>
</dependency>
<!-- freemarker-->
    <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>

代码

package com.llf;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class MybatisPlusCode {
    


    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
    
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
    
            String ipt = scanner.next();
            if (StringUtils.isNotBlank(ipt)) {
    
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }

    public static void main(String[] args) {
    
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        /**
         全局配置
         */
        GlobalConfig gc = new GlobalConfig();
        //扫描当前路径
        String projectPath = System.getProperty("user.dir");
        //代码生成在/src/main/java目录下
        gc.setOutputDir(projectPath + "/src/main/java");
        //作者名字
        gc.setAuthor("llf");
        //是否打开生成后的文件夹
        gc.setOpen(false);
        //实体属性 Swagger2 注解
        gc.setSwagger2(true);
        mpg.setGlobalConfig(gc);

        /**
         *
         / 数据源配置
         *
         */
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/mybatis-plus? useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
        // dsc.setSchemaName("public");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123456");
        //将数据源仍进代码生成器
        mpg.setDataSource(dsc);

        /**
         * 包配置
         */
        PackageConfig pc = new PackageConfig();
        // 模块名
        pc.setModuleName(scanner("模块名"));
        //项目包结构 例如com.llf.xxx
        pc.setParent("com.llf");
        //实体类包名
        pc.setEntity("Pojo");
        //Mapper包名
        pc.setMapper("Mapper");
        //Service包名
        pc.setService("Service");
        //去掉service的前缀
        gc.setServiceName("%sService");
        //ServiceImpl包名
        pc.setServiceImpl("ServiceImpl");
        //Mapperxml包名
        pc.setXml("Mapperxml");
        //将包结构设置仍进生成器
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
    
            @Override
            public void initMap() {
    
                // to do nothing
            }
        };

        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
    
            @Override
            public String outputFile(TableInfo tableInfo) {
    
                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        /*
        cfg.setFileCreate(new IFileCreate() {
            @Override
            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
                // 判断自定义文件夹是否需要创建
                checkDir("调用默认方法创建的目录,自定义目录用");
                if (fileType == FileType.MAPPER) {
                    // 已经生成 mapper 文件判断存在,不想重新生成返回 false
                    return !new File(filePath).exists();
                }
                // 允许生成模板文件
                return true;
            }
        });
        */
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        // 配置自定义输出模板
        //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
        // templateConfig.setEntity("templates/entity2.java");
        // templateConfig.setService();
        // templateConfig.setController();

        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        //包名类名驼峰自动转换
        strategy.setNaming(NamingStrategy.underline_to_camel);
        //数据库字段驼峰自动转换
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        //实体类字段Lambok
        strategy.setEntityLombokModel(true);
        //Controller自动restful风格
        strategy.setRestControllerStyle(true);
        strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix(pc.getModuleName() + "_");
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ezwgW6f7-1627193026481)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210725135727744.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FSMd1Gya-1627193026482)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210725135910690.png)]

问题注意

为什么JPA不能使用?
JPA提示的方式需要根据Mapper找到实体类, 找到实体类有以下五种方式

  1. 继承mybatis-plus的BaseMapper
  2. Mapper.xml 文件有 resultMap 标签
  3. 在Mapper类上增加注释指定实体类, 例如: @Entity com.xx.xx.UserModel

为什么生成的表名和期望的表名不一致
JPA提示生成代码, 按照以下规则找到表名

  1. 实体类有JPA注解, 例如: @Table(name="t_user")
  2. 实体类有mybais-plus注解, 例如: @TableName("t_user")
  3. 实体类有注释: @TableName com.xx.xx.UserModel
  4. 如果不存在以上规则, 将驼峰转下划线. 例如 UserMode 的表名为: user_model

拓展

如果觉得这样子配置很麻烦,我们可以试试官方新出的MybatisX的插件 它简化了更多配置 可以说是安装即用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JWdzA5Mn-1627193026482)(C:\Users\machenike\AppData\Roaming\Typora\typora-user-images\image-20210725140300853.png)]

https://mp.baomidou.com/guide/mybatisx-idea-plugin.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Amazing66/article/details/119081282

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签