MyBatis-plus

MyBatis-plus学习结构图

1.MyBatis-plus简介

为什么要学习它呢?MyBatisPlus可以节省我们大量工作时间,所有的CRUD代码它都可以自动化完成! JPA、 tk-mapper、MyBatisPlus 偷懒的! MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

2.快速入门

地址:快速开始 | MyBatis-Plus

根据官网实现入门:

步骤:
​
1.创建数据库
use mybatis_plus;
​
create table if not exists student(
    id BIGINT(11) not null auto_increment comment'主键id',
    `name` varchar(255) null default null comment'姓名',
        age int(4) null default null comment'年龄',
        email varchar(50) null default null comment '邮箱',
        primary key(`id`)
)ENGINE =INNODB default CHARSET=utf8;
​
INSERT INTO student (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
2.创建一个SpringBoot项目并配置相关配置
pom.xml以来导入
 
<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 </dependency>
 <dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 </dependency>
 <!--        mybatis-plus-->
 <dependency>
 <groupId>com.baomidou</groupId>
 <artifactId>mybatis-plus-boot-starter</artifactId>
 <version>3.0.5</version>
 </dependency>
​
application.yaml文件

spring:
  application:
    name: my
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver #启动
server:
  port: 8080 #端口
  servlet:
    context-path: /api #配置上下文
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #日志
    cache-enabled: true #缓存
    map-underscore-to-camel-case: true #大小写
  mapper-locations: classpath:mapper/*.xml #mapper.xml映射
​
​
3.实体类、mapper接口编写及测试
实体类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

mapper接口:(BaseMapper是MyBatis-plus提供的一些方法额接口)
@Repository
public interface StudentMapper extends BaseMapper<Student> {
}
​
测试类:

@SpringBootTest
public class MyApplicationTests {
    @Autowired
    private StudentMapper studentMapper;
​
    @Test
    public void studentList(){
        List<Student> students=studentMapper.selectList(null);
        students.forEach(System.out::println);
    }
}

3.主键自增策略

Insert语句(暴露主键自增):

@Test
    public void addStudent(){
        Student student=new Student(null,"漳卅",67,"3487675116@qq.com");
        studentMapper.insert(student);
    }

根据日志结果会轻易发现:id值自动生成

Preparing: INSERT INTO student ( id, name, age, email ) VALUES ( ?, ?, ?, ? ) 
Parameters: 1584015180068241410(Long), 漳卅(String), 67(Integer), 3487675116@qq.com(String)
Updates: 1

主键生成默认是ID_WORKER 全局唯一id:了解分布式系统唯一id生成:分布式系统唯一ID生成方案汇总 - nick hao - 博客园 雪花算法:snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯一!

主键生成策略具体实现简单就是:给实体类id属性添加@TableId(type= IdType.INPUT)注解

@Getter
public enum IdType {
    /**
     * 数据库ID自增
     */
    AUTO(0),
    /**
     * 该类型为未设置主键类型
     */
    NONE(1),
    /**
     * 用户输入ID
     * 该类型可以通过自己注册自动填充插件进行填充
     */
    INPUT(2),
​
    /* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
    /**
     * 全局唯一ID (idWorker)
     */
    ID_WORKER(3),
    /**
     * 全局唯一ID (UUID)
     */
    UUID(4),
    /**
     * 字符串全局唯一ID (idWorker 的字符串表示)
     */
    ID_WORKER_STR(5);
    private int key;
    IdType(int key) {
        this.key = key;
    }
}

4.自动填充

create_time与update_time是我们创建表时需要创建的字段,但不需要我们手动添加值更新,因此时间的自动填充是需要的,自动填充分为数据库与后端代码实现两种。这里不仅针对于时间(图有误)

数据库实现: 新增两个字段一个是create_time,另一个是update_time,这两个默认值设置为CURRENT_TIMESTAMP。这样既可以给时间设置自动填充。

代码实现: 去掉create_time和update_time默认值,并给实体类添加两个属性,一个createTime,另一个updateTime。

@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
​
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;

@TableFiled表示表字段,fill表示填充。填充类型查值是填充还是更新时填充等等。 但要实现自动填充,我们还要实现一个处理器MetaObjectHandler,用来处理时间:

@Component  //一定不要忘记把处理器加到IOC容器中
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
    //插入时候的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ......");
        //default MetaObjectHandler
        //setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
        this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);
        this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
    }
​
    //更新时候的填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ......");
        this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
    }
}

测试:

@Test
    public void addStudent(){
        Student student=new Student(null,"雪域",25,"3487675116@qq.com",null,null);
        studentMapper.insert(student);
    }

5.乐悲观锁

乐观锁:顾名思义十分乐观,他总是认为不会出现问题,无论干什么都不去上锁!如果出现了问题,再次更新值测试

悲观锁:顾名思义十分悲观,他总是认为出现问题,无论干什么都会上锁!再去操作!

乐观锁实现方式:

1.取出数据获取version值 2.更新时带上version值 3.执行更新时判断version与之前version是否一致 4.如果不对更新失败

百度百科:

如一个金融系统,当某个操作员读取用户的数据,并在读出的用户数据的基础上进行修改时(如更改用户帐户余额),如果采用悲观锁机制,也就意味着整个操作过 程中(从操作员读出数据、开始修改直至提交修改结果的全过程,甚至还包括操作 员中途去煮咖啡的时间),数据库记录始终处于加锁状态,可以想见,如果面对几百上千个并发,这样的情况将导致怎样的后果。
乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本 ( version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。
读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。同时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号等于数据库表当前版本号,则予以更新,否则认为是过期数据。
对于上面修改用户帐户信息的例子而言,假设数据库中帐户信息表中有一个 version 字段,当前值为 1 ;而当前帐户余额字段( balance )为 $100 。

具体乐观锁简单实现:

1.数据库新增version字段默认值为1,并给实体类添加属性version

@Version    //乐观锁version注解
private Integer version;

2.配置乐观锁插件,OptimisticLockerInterceptor

//扫描我们的mapper文件夹
@MapperScan("com.my.mapper")
@EnableTransactionManagement
@Configuration  //配置类
public class MyBatisPlusConfig {
    //注册乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}

3.测试

   
 @Test
    public void versionStudent(){
        // 测试乐观锁失败!多线程下
        // 线程1
        Student student1 = studentMapper.selectById(1L);
        student1.setName("shen111");
        student1.setEmail("6666666@qq.com");
​
        // 模拟另外一个线程执行了插队操作
        Student student2 = studentMapper.selectById(1L);
        student2.setName("shen222");
        student2.setEmail("6666666@qq.com");
        studentMapper.updateById(student2);
​
        //自旋锁来多次尝试提交!
        studentMapper.updateById(student1); //如果没有乐观锁就会覆盖插队线程的值
    }

乐观锁可以防止多个线程操作同一资源。

6.分页查询

MyBatis-plus自带分页插件,因此我们实现分页查询也比较简单。只需要我们配置分页插件即可,并调用分页方法。

//扫描我们的mapper文件夹
@MapperScan("com.my.mapper")
@EnableTransactionManagement
@Configuration  //配置类
public class MyBatisPlusConfig {
    //分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}
@Test
    public void pageStudent(){
        Page<Student> page=new Page<>(1,3);
        IPage<Student> studentIPage = studentMapper.selectPage(page, null);
    }

日志输出:

 JsqlParserCountOptimize sql=SELECT  id,name,age,email,create_time,update_time,version  FROM student
==>  Preparing: SELECT COUNT(1) FROM student 
==> Parameters: 
<==    Columns: COUNT(1)
<==        Row: 7
==>  Preparing: SELECT id,name,age,email,create_time,update_time,version FROM student LIMIT 0,3 
==> Parameters: 
<==    Columns: id, name, age, email, create_time, update_time, version
<==        Row: 1, shen222, 18, 6666666@qq.com, null, 2022-10-23 03:36:58, 2
<==        Row: 2, Jack, 20, test2@baomidou.com, null, null, 1
<==        Row: 3, Tom, 28, test3@baomidou.com, null, null, 1
<==      Total: 3

7.逻辑删除

物理删除:从数据库中直接移除 逻辑删除:在数据库中没有被移除,而是通过一个变量来让他失效!deleted=0 —> deleted=1

对于用户来说有一些数据可以被删除,但对于管理员来说,数据有可能不该被物理删除,因此在删除数据时,我们会考虑逻辑删除。一样要实现逻辑删除,我们要添加一个字段delete(默认值为1)给数据库,并给实体类添加相应属性。

@TableLogic
private Integer deleted;

配置逻辑删除组件:

// 逻辑删除组件
    @Bean
    public ISqlInjector sqlInjector(){
        return new LogicSqlInjector();
    }

配置逻辑删除mybatis-plus的删除与未删除的默认值:

# 配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

测试:

@Test
public void deleteStudent(){
    studentMapper.deleteById(1584015180068241412L);
}

日志输出:逻辑删除简单就是执行了一条更新语句。但是用户在再执行查询是没有结果的。

==>  Preparing: UPDATE student SET deleted=1 WHERE id=? AND deleted=0 
==> Parameters: 1584015180068241412(Long)
<==    Updates: 1

8.性能分析插件

MyBatis-plus也自带性能分析插件(如同ali的druid),可以设置sql执行时长,如果超过这个时间就停止运行!

性能插件配置:

// SQL执行效率插件
@Bean
@Profile({"dev","test"})// 设置dev test 环境开启,保证我们的效率
public PerformanceInterceptor performanceInterceptor(){
    PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
    performanceInterceptor.setMaxTime(100); //ms 设置sql执行的最大时间,如果超过了则不执行
    performanceInterceptor.setFormat(true); // 是否格式化代码
    return performanceInterceptor;
}

修改一下spring-profiles.active=dev 最后测试一下我们的查询语句:(超时报错)

 Time:0 ms - ID:com.my.mapper.StudentMapper.deleteById
Execute SQL:
    UPDATE
        student 
    SET
        deleted=1 
    WHERE
        id=1584015180068241412 
        AND deleted=0

9.条件构造器

MyBatis不仅提供BaseMapper接口,为了业务层还提供了Iservice接口及ServiceImpl实现类。因此我们在使用的使用,注解IStudentService继承接口IService,实现类StudentService继承ServiceImpl类。IService提供的方法比BaseMapper更多。 条件构造器就是为了实现复杂的SQL语句而提供的。

QueryWrapper<T> 是一个泛型类,我们需要创建一个这样的对象,然后根据这个对象调用相应的方法来完成条件的构造。
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper常用方法如下:
    eq()            =
    ne()            <>
    gt()            >
    ge()            >=
    lt()            <
    le()            <=
    select()        指定查询字段
    between()        between .. and ..
    notBetween()    not between .. and ..
    like()          like '%值%'
    likeLeft()      like '%值'
    likeRight()     like '值%'
    notLike()       not like '%值%'
    isNull()        is null
    isNotNull()     is not null
    in()            in (?,?,?)
    notIn()         not in (?,?,?)
    inSql()         in (SQ语句,需要避免SQL注入)
    notInSql()      not in (SQL语句)
    exists()        exists (SQL语句)
    notExists()     not exists (SQL语句)
    orderByAsc()    ORDER BY 字段 ASC       
    orderByDesc()   ORDER BY 字段 DESC       
    and()           and
    or()            or
    apply           拼接自定义SQL语句(可以使用{n}占位,以避免SQL注入)
    last()          在最后追加自定义SQL语句

下面是上面的方法基本使用格式:

@Resource
IUserService userService;
​
/**
* 测试 getById()
*/
@Test
public void testGetById() {
Integer id = 2; //用户ID
User user = userService.getById(id);
log.info("结果:");
log.info(ViewUtils.view(null, user, 200));
}
​
/**
* 测试 getOne()
*/
@Test
public void testGetOne() {
String username = "jack";
String password = "123456";
QueryWrapper<User> queryWrapper = new QueryWrapper();   //条件构造器
queryWrapper.select("id", "username", "realname", "mobile");  //查询指定字段
queryWrapper.eq("username", username)
.apply("password = MD5({0})", username + password);
User user = userService.getOne(queryWrapper);
log.info("结果:");
log.info(ViewUtils.view(null, user, 200));
}
​
/**
* 测试 getObj()
*/
@Test
public void testGetObj() {
String username = "jack";
String password = "123456";
QueryWrapper<User> queryWrapper = new QueryWrapper();   //条件构造器
queryWrapper.select("id");  //查询指定字段
queryWrapper.eq("username", username)
.apply("password = MD5({0})", username + password);
Integer id = userService.getObj(queryWrapper, o -> Integer.parseInt(o.toString()));
log.info("结果:");
if (id == null) {
log.info(ViewUtils.view("ID为空,用户名密码错误", null, 402));
} else {
log.info(ViewUtils.view("查询到ID了", id, 200));
}
}
​
/**
* 测试 getMap()
*/
@Test
public void testGetMap() {
String username = "jack";
String password = "123456";
QueryWrapper<User> queryWrapper = new QueryWrapper();   //条件构造器
queryWrapper.select("id", "username", "realname", "mobile");  //查询指定字段
queryWrapper.eq("username", username)
.apply("password = MD5({0})", username + password);
Map<String, Object> map = userService.getMap(queryWrapper);
log.info("结果:");
log.info(ViewUtils.view(null, map, 200));
}
​
​
/**
* 测试 list()
*
* sql where1: id > ? AND role_id <> ? OR (age <= ? AND username LIKE ?) AND department_id IN (select*****
* sql where1: id > ? AND role_id <> ? AND (age <= ? OR username LIKE ?) AND department_id IN (select*****
*
*/
@Test
public void testList() {
QueryWrapper<User> queryWrapper = new QueryWrapper();
queryWrapper.select("id", "username", "realname", "mobile");  //查询指定字段
queryWrapper.gt("id", 1);
queryWrapper.ne("role_id", 1);
//        queryWrapper.or(wrapper -> wrapper.le("age", 45)
//                                          .like("username", "zh"));
queryWrapper.and(wrapper -> wrapper.le("age", 45)
.or()
.like("username", "zh"));
//        queryWrapper.le("age", 45);
//        queryWrapper.like("username", "zh");
queryWrapper.inSql("department_id", "select id from department where name in('财务室','后勤部')");
queryWrapper.orderByAsc("id");
queryWrapper.last("limit 5");
List<User> users = userService.list(queryWrapper);
log.info("结果:");
log.info(ViewUtils.view(null, users, 200));
}
​
/**
* 测试 listObj()
*/
@Test
public void testListObj() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.select("id");  //查询指定字段
queryWrapper.gt("id", 1);
List<Integer> ids = userService.listObjs(queryWrapper, o -> Integer.parseInt(o.toString()));
log.info("结果:");
log.info(ViewUtils.view(null, ids, 200));
}
​
​
/**
* 测试 listMap()
*/
@Test
public void testListMap() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.select("id", "username", "realname", "mobile");  //查询指定字段
queryWrapper.gt("id", 1);
List<Map<String, Object>> mapList = userService.listMaps(queryWrapper);
log.info("结果:");
log.info(ViewUtils.view(null, mapList, 200));
}
​
/**
* 测试 count()
*/
@Test
public void testCount() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.gt("id", 1);
Long count = userService.count(queryWrapper);
log.info("结果:");
log.info(ViewUtils.view(null, count, 200));
}
​
​
/**
* 测试 page()
*/
@Test
public void testPage() {
Integer pageIndex = 2;  //页码
Integer pageSize = 3;   //页大小
​
Page page = new Page(pageIndex, pageSize);  //创建一个Page对象,该对象包含了页码、页大小等属性
QueryWrapper queryWrapper = new QueryWrapper(); //条件构造器
queryWrapper.select("id", "username", "realname", "mobile");  //查询指定字段
queryWrapper.gt("id", 1);
​
IPage<User> userIPage = userService.page(page, queryWrapper);
log.info("结果:");
log.info(ViewUtils.view(null, userIPage, 200));
}
​
/**
* 测试 pageMaps()
*/
@Test
public void testPageMaps() {
Integer pageIndex = 2;  //页码
Integer pageSize = 3;   //页大小
​
Page page = new Page(pageIndex, pageSize);  //创建一个Page对象,该对象包含了页码、页大小等属性
QueryWrapper queryWrapper = new QueryWrapper(); //条件构造器
queryWrapper.select("id", "username", "realname", "mobile");  //查询指定字段
queryWrapper.gt("id", 1);
​
IPage<Map<String, Object>> userIPage = userService.pageMaps(page, queryWrapper);
log.info("结果:");
log.info(ViewUtils.view(null, userIPage, 200));
}
​
@Resource
IRoleService roleService;
​
/**
* 测试 save()
*/
@Test
public void testSave() {
//        User user = new User("caocao", "MD5('123456')", );
Role role = new Role(0, "打更的");
boolean success = roleService.save(role);
if (success) {
log.info(ViewUtils.view("新增成功", null, 200));
log.info("当前插入的对象的ID:" + role.getId());
}
}
​
/**
* 测试 updateById()
*/
@Test
public void testUpdateById() {
//        Role role = new Role(16, "跑堂的");
//        boolean success = roleService.updateById(role);
//        if (success) {
//            log.info(ViewUtils.view("修改成功", null, 200));
//        }
​
User user = userService.getById(2);
user.setAge((short) 22);
log.info("结果:" + userService.updateById(user));
​
}
​
​
/**
* 测试 update
*/
@Test
public void testUpdate() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.gt("age", 40);
​
User user = new User();
user.setAuthority("articleList,articleAdd");
​
log.info("结果:" + userService.update(user, queryWrapper));
}
​
/**
* 测试 removeById
*/
@Test
public void testRemoveById() {
log.info("结果:" + userService.removeById(11));
}
​
/**
* 测试 removeByIds
*/
@Test
public void testRemoveByIds() {
List<Integer> ids = Arrays.asList(2, 4, 5, 6, 7, 8, 11);
log.info("结果:" + userService.removeByIds(ids));
}
​
​
/**
* 测试 remove复杂用法
*/
@Test
public void testRemove() {
/*
条件1:id属于ids集合里面的数据
条件2:性别等于女
*/
List<Integer> ids = Arrays.asList(2, 4, 5, 6, 7, 8, 11);
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.in("id", ids);
queryWrapper.eq("sex", "女");
log.info("结果:" + userService.remove(queryWrapper));
}
​
@Resource
IUserMapper userMapper;
​
/**
* 测试 自定义SQL
*/
@Test
public void testMyCustomSQL() {
Integer pageIndex = 1;  //页码
Integer pageSize = 3;   //页大小
​
Integer minAge = 10;    //最小年龄
String sex = "男";       //性别
String realname = null;  //姓名
​
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.gt("user.id", 1);
queryWrapper.ge("age", minAge);
queryWrapper.eq("sex", sex);
if (realname != null) queryWrapper.likeRight("realname", realname);
queryWrapper.between("age", 20, 50);
queryWrapper.in("department.name", Arrays.asList("财务室", "后勤部"));
​
//        List<Map<String, Object>> maps = userMapper.selectUserJoinDetAndRol(queryWrapper);    //获取用户列表(无分页)
Page page = new Page(pageIndex, pageSize);  //创建一个Page对象,该对象包含了页码、页大小等属性
IPage<Map<String, Object>> userPage = userMapper.selectUserJoinDetAndRolPage(page, queryWrapper);
​
log.info("结果:");
log.info(ViewUtils.view(null, userPage, 200));
}

10.代码自动生成器

AutoGenerator是Mybatis-Plus的代码生成器,通过AutoGenerator可以快速生成Entity、Mapper、MapperXML、Service、Controller等各个模块的代码,极大的提升了开发效率。

public class Code {
    public static void main(String[] args) {
        //需要构建一个 代码自动生成器 对象
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        //配置策略
​
        //1、全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("mougenan");
        gc.setOpen(false);
        gc.setFileOverride(false);  //是否覆盖
        gc.setServiceName("%sService"); //去Service的I前缀
        gc.setIdType(IdType.ID_WORKER);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setSwagger2(true);
        mpg.setGlobalConfig(gc);
​
        //2、设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123456");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);
​
        //3、包的配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName("blog");
        pc.setParent("com.my");
        pc.setEntity("pojo");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setController("controller");
        mpg.setPackageInfo(pc);
​
        //4、策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("user");    //设置要映射的表名
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);    //自动lombok
        strategy.setLogicDeleteFieldName("deleted");
        //自动填充配置
        TableFill createTime = new TableFill("create_time", FieldFill.INSERT);
        TableFill updateTime = new TableFill("update_time", FieldFill.UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(createTime);
        tableFills.add(updateTime);
        strategy.setTableFillList(tableFills);
        //乐观锁
        strategy.setVersionFieldName("version");
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true);     //localhost:8080/hello_id_2
        mpg.setStrategy(strategy);
​
        mpg.execute();  //执行代码构造器
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我愿为一粒沙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值