MybatisPlus的简单使用

1. 概述

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

2. 快速入门

2.1 引入相关依赖

创建maven工程,编写pom文件如下:

<!-- 指定SpringBoot父工程-->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.4.RELEASE</version>
</parent>

<dependencies>
    
    <!--mybatisplus启动器,传递依赖了JDBC启动器-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.0</version>
    </dependency>
    
    <!-- mysql驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>

    <!-- 单元测试启动器-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    
</dependencies>

2.2 编写DataSource相关配置

resources目录下创建application.yml配置文件

# datasource
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mp # localhost:3306改成自己的数据库地址
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver

2.3 编码

mapper数据访问层:

package cn.it.dao;

import cn.it.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * 使用mp定义Mapper,需要让Mapper接口继承 BaseMapper接口。
 */
public interface UserMapper extends BaseMapper<User> {
}

实体类:

package cn.it.pojo;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;


/**
 * 用户实体类
 */
@TableName("tb_user") // 指定表名
@Data
public class User {
@TableId(type = IdType.AUTO)
    private Long id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private String email;
}

启动类增加 @MapperScan 注解

package cn.it;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 启动类
 *
 * @Author 
 * @Date 2020/11/23
 */
@MapperScan("cn.it.dao") // 指定mapper包路径
@SpringBootApplication
public class MybatisPlusSpringbootApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusSpringbootApplication.class, args);
    }
}

2.4测试:

package cn.it;

import cn.it.dao.UserMapper;
import cn.it.pojo.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * 用户数据访问层单元测试类
 *
 * @Author 
 * @Date 2020/11/23
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {

    @Autowired
    private UserMapper userMapper;


    /**
     * 根据id查询用户
     */
    @Test
    public void testSelectById(){
        User user = userMapper.selectById(1l);
        System.out.println("user = " + user);
    }
}

3.通用CRUD-新增

3.1 改造实体

/**
 * 实体类的属性名和数据库的字段名自动映射:
 * 1.名称一样
 * 2.数据库字段使用_分割,实体类属性名使用驼峰名称
 */
@TableName("tb_user")
@Data
public class User {

    // 设置id生成策略:AUTO,数据库主键自增
    @TableId(type = IdType.AUTO)
    private Long id;
    // @TableField("user-name")
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private String email;

   // 不希望该值存入数据库
   // @TableField(exist = false)
   // private String info;

}

3.2 @TableField注解说明

1)  @TableField("user_name") 指定映射关系
实体类的属性名和数据库的字段名自动映射:
    * 名称一样
    * 数据库字段使用_分割,实体类属性名使用驼峰名称
否则需要使用 @TableField("user_name") 指定映射关系

2)  忽略某个字段的查询和插入
    @TableField(exist = false) 

3)  设置id生成策略:AUTO 数据库主键自增
    @TableId(type = IdType.AUTO)

3.3 属性配置说明

mybatis-plus:
  global-config:
    db-config:
      # 表名前缀,设置后,如果数据库表名是tb_user, 那么实体类上可以不添加@TableName注解,不建议这里统一设置
      table-prefix: tb_
      # 全局默认主键类型,设置后,即可省略实体对象中的@TableId(type = IdType.AUTO)配置, 不建议这里统一设置
      id-type: auto 
  configuration:
    # 日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3.4 单元测试

/**
 * 新增用户
 */
@Test
public void testInsert(){
    User user = new User();
    user.setUserName("zhuge");
    user.setName("诸葛孔明");
    user.setPassword("123456");
    user.setInfo("三国之卧龙"); // 不会保存到数据库,因为在实体类设置了@TableField(exist = false)

    userMapper.insert(user);
}

4.通用CRUD-删除

4.1 根据id删除


/**
 * 根据id删除用户
 */
@Test
public void testDeleteById(){
    // 返回值代表删除成功的记录数
    int count = userMapper.deleteById(6l);
}

4.2 根据id集合批量删除

/**
 * 根据ID集合批量删除
 */
@Test
public void testDeleteByBatchIds(){
    List<Long> ids = new ArrayList();
    ids.add(4l);
    ids.add(5l);

    // 返回值代表删除成功的记录数
    int count = userMapper.deleteBatchIds(ids);
}

4.3 根据map条件删除

/**
 * 根据Map条件删除
 */
@Test
public void testDeleteByMap(){
    Map<String, Object> queryParams = new HashMap<>();
    // 参数1-代表数据库字段名,参数2-匹配的值
    // 注意:map中如果put多个判断条件,默认以and连接
    queryParams.put("user_name", "zhangsan"); // 相当于where user_name = 'zhangsan'
    queryParams.put("age", 18);

    // count代表删除成功的记录数
    int count = userMapper.deleteByMap(queryParams);
}

4.4 根据条件构造器删除

/**
 * 根据条件构造器删除
 */
@Test
public void testDeleteByWrapper(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // 参数1-字段名,参数2-匹配的值
    wrapper.eq("user_name", "lisi");
    
    // count代表删除成功的记录数
    int count = userMapper.delete(wrapper);

}

5.通用CRUD-更新

5.1 根据id更新

/**
 * 根据id更新
 */
@Test
public void testUpdateById(){
    User user = new User();
    user.setId(1l); // 必须设置,因为是根据id更新
    user.setAge(100); // 修改后的值

    // 修改成功的记录数
    int count = userMapper.updateById(user);
}

5.2 根据条件构造器更新

/**
 * 根据条件构造器更新
 */
@Test
public void testUpdateByWrapper() {
    // user对象为修改后的值
    User user = new User();
    user.setName("司马懿");
    user.setAge(60);

    // where条件
    UpdateWrapper<User> updateWrapper = new UpdateWrapper();
    updateWrapper.eq("user_name", "zhangsan");

    int count = userMapper.update(user, updateWrapper);
}

6.通用CRUD-查询

6.1 基本比较查询

语法

eq( ) :  等于 =
ne( ) :  不等于 <>
gt( ) :  大于 >
ge( ) :  大于等于 >=
lt( ) :  小于 <
le( ) :  小于等于 <=
between ( ) :  BETWEEN 值1 AND 值2 
notBetween ( ) :  NOT BETWEEN 值1 AND 值2 
in( ) :  in
notIn( ) :  not in

测试

/**
 * 基本比较查询
 */
@Test
public void testWrapper1(){
    // 创建查询条件构造器
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    // 设置查询条件
    queryWrapper.eq("user_name", "lisi")
        .lt("age", 23)
        .in("name", "李四", "王五");

    // select * from tb_user where user_name = 'lisi' and age < 23 and name in ('李四', '王五')
    List<User> userList = userMapper.selectList(queryWrapper);
    for (User user : userList) {
        System.out.println("user = " + user);
    }
}

6.2 逻辑查询

语法

and 参数为Consumer lamboda表达式
or 后面接其他条件基本比较查询的条件

测试

/**
 * 逻辑查询-or
 */
@Test
public void testWrapper2(){
    // 创建查询条件构造器
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    // 设置查询条件
    queryWrapper.eq("user_name", "lisi")
                .or() // 不加or默认是以and连接多个条件
                .gt("age", 10);


    // select * from tb_user where user_name = 'lisi' or age > 10
    List<User> userList = userMapper.selectList(queryWrapper);
    for (User user : userList) {
        System.out.println("user = " + user);
    }
}


/**
 * 逻辑查询-and
 */
@Test
public void testWrapper3(){
    // 创建查询条件构造器
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    // 设置查询条件
    queryWrapper.eq("user_name", "lisi")
            // 相当于and (), ()中可指定多个条件
            .and(i-> i.eq("name", "王五").or().eq("name", "赵六"));

    // select * from tb_user where user_name = 'lisi' and (name = '王五' or name = '赵六')
    List<User> userList = userMapper.selectList(queryWrapper);
    for (User user : userList) {
        System.out.println("user = " + user);
    }
}

6.3 模糊查询

语法

like 相当于 like '%关键字%'
notLike 相当于 not like '%关键字%'
likeLeft 相当于 like '%关键字'
likeRight 相当于 like '关键字%'

测试

/**
 * 模糊查询
 */
@Test
public void testWrapper4(){
    // 1.创建查询条件构建器
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // 2.设置条件
    wrapper.likeRight("user_name","zhang");

    // SELECT * from tb_user where user_name like 'zhang%'
    List<User> userList = userMapper.selectList(wrapper);
    for (User user : userList) {
        System.out.println("user = " + user);
    }
}

6.4 排序查询

/**
 * 排序
 */
@Test
public void testWrapper5() {
    // 1.创建查询条件构建器
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // 2.设置条件
    wrapper.lt("age", 50)
        // 参数1:是否要作为条件(肯定为true啦),参数2-是否升序(true为升序),参数3-排序字段名
        .orderBy(true, true, "age");

    // select * from tb_user where age < 50 order by age asc
    List<User> userList = userMapper.selectList(wrapper);
    for (User user : userList) {
        System.out.println("user = " + user);
    }
}

6.5 select

问题:查询相关API默认是返回所有字段,相当于select * from 表名,若想要指定返回的字段就可以使用select API。

@Test
public void testWrapper6(){
    // 1.创建查询条件构建器
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // 2.设置条件
    wrapper.eq("user_name", "lisi")
        .or()
        .lt("age", 23)
        .in("name", "李四", "王五")
        //.orderBy(true, true, "age")
        .orderByDesc("age")
        .select("id", "user_name"); // 指定要返回的字段
    /*
      select id, user_name from tb_user where user_name = ? or age < ? and name in (?,?) order by age asc
     */
    List<User> users = userMapper.selectList(wrapper);
    System.out.println(users);
    }

6.6 分页查询

编写配置类,添加拦截器

package cn.it.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class PageConfig {

    /**
     * 3.4.0之前的版本用这个
     * @return
     */
    
    /* 
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return  new PaginationInterceptor();
    }
    */

    /**
     * 3.4.0之后提供的拦截器的配置方式
     * @return
     */
   @Bean
   public MybatisPlusInterceptor mybatisPlusInterceptor(){
       MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
       mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
       return mybatisPlusInterceptor;
   }
}

测试

/**
 * 分页查询
 */
@Test
public void testWrapper7() {
    // 1.创建查询条件构建器
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // 2.设置条件
    wrapper.lt("age", 50)
        .select("user_name", "age") // 只返回user_name和age字段
        .orderBy(true, true, "age");

    // 3.创建分页对象,参数1-当前页,参数2-每页显示数
    Page<User> page = new Page<>(1, 2);

    // select user_name, age from tb_user where age < 50 order by age asc limit 0,2
    userMapper.selectPage(page, wrapper);

    List<User> records = page.getRecords(); // 用户数据
    long total = page.getTotal(); // 总条数
    long pages = page.getPages(); // 总页数

    for (User user : records) {
        System.out.println("user = " + user);
    }
    System.out.println("总条数 = " + total);
    System.out.println("总页数 = " +pages);
}

7.使用原生mybatis

问题:上面讲解的API 都是Mybatis Plus对于单表CRUD进行的封装,那在实际开发中,可能存在复杂sql的编写,例如:多表联查,子查询等等,此类操作就需要开发人员使用原生Mybatis的功能,自己写sql语句了。

7.1 基本使用

第一步:yml文件中配置相关属性

mybatis-plus:
  global-config:
    db-config:
      # 全局设置自增,设置后,实体类中不需要通过@TableId()
      id-type: auto
      table-prefix: tb_
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印sql
    # 设置sql返回字段驼峰转换
    map-underscore-to-camel-case: true
  # 指定xml文件路径
  mapper-locations:
    - classpath:/mappers/*.xml
  # 返回值别名包路径
  type-aliases-package: cn.itcast.pojo

第二步:resoures目录下创建mappers文件夹,然后在mappers文件夹下创建UserMapper.xml文件,可使用插件J2EECfgFile创建。

第三步:编写UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--指定userMapper接口的路径-->
<mapper namespace="cn.it.dao.UserMapper">

	<select id="findById" resultType="User">
		select * from tb_user where id = #{id}
	</select>
</mapper>

第四步:编写UserMapper.java接口

package cn.it.dao;

import cn.it.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * 使用mp定义Mapper,需要让Mapper接口继承 BaseMapper接口。
 */
public interface UserMapper extends BaseMapper<User> {

    /**
     * 根据id查询用户
     * @param id
     * @return
     */
    public User findById(Long id);
}

第五步:测试

/**
 * 测试自定义sql
 */
@Test
public void testFindById(){
    User user = userMapper.findById(1l);
    System.out.println("user = " + user);
}

7.2 分页查询

第一步:编写UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--指定userMapper接口的路径-->
<mapper namespace="cn.itcast.dao.UserMapper">

   

   <!--分页查询-->
   <select id="selectAllByPage" resultType="User">
      select * from tb_user 
   </select>

</mapper>

第二步:编写UserMapper.java接口,添加方法

/**
 * 分页查询
 * @param page
 * 
 * @return
 */
public Page<User> selectAllByPage(Page page);

第三步:测试

/**
 * 测试自定义分页查询
 */
@Test
public void testSelectAllByPage(){
    // 定义分页对象
    Page<User> page = new Page<>(1, 2);

    userMapper.selectAllByPage(page);

    List<User> records = page.getRecords(); // 返回用户数据
    long total = page.getTotal(); // 总条数
    long pages = page.getPages(); // 总页数

    for (User user : records) {
        System.out.println("user = " + user);
    }
    System.out.println("总条数 = " + total);
    System.out.println("总页数 = " +pages);
}

8.通用枚举

解决了繁琐的配置,让 mybatis 优雅的使用枚举属性!

第一步:修改表结构

ALTER TABLE `tb_user` ADD COLUMN `sex` int(1) NULL DEFAULT 1 COMMENT '1-男,2-女';

第二步:定义枚举类

package cn.it.enums;

import com.baomidou.mybatisplus.annotation.IEnum;

/**
 * 性别枚举类
 *
 * @Author 
 * @Date 2020/11/24
 */
public enum SexEnum implements IEnum<Integer> {

    MAN(1, "男"),
    WOMEN(2, "女");

    private int value;
    private String desc;

    SexEnum(int value, String desc) {
        this.value = value;
        this.desc = desc;
    }

    @Override
    public Integer getValue() {
        return this.value;
    }

    @Override
    public String toString() {
        return this.desc;
    }
}

第三步:修改yml配置,扫描枚举类所在包

mybatis-plus:
  global-config:
    db-config:
      # 全局设置自增,设置后,实体类中不需要通过@TableId()
      id-type: auto
      table-prefix: tb_
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印sql
    # 设置sql返回字段驼峰转换
    map-underscore-to-camel-case: true
  # 指定xml文件路径
  mapper-locations:
    - classpath:/mappers/*.xml
  # 返回值别名包路径
  type-aliases-package: cn.it.pojo
  # 指定枚举类包路径
  type-enums-package: cn.it.enums

第四步:修改实体类,增加性别字段

private SexEnum sex;

第五步:测试

@Test
public void testEnum1(){
    List<User> users = userMapper.selectList(null);

    for (User user : users) {
        System.out.println("user = " + user);
    }
}

查询时自动将数据库的数据由 1 转为了 男(会使用枚举类的重写的toString方法返回值)。

/**
 * 测试通用枚举-新增
 */
@Test
public void testEnum2(){
    User user = new User();
    user.setName("赵子龙");
    user.setAge(18);
    user.setUserName("zhaozilong");
    user.setPassword("123456");
    user.setEmail("1111@sina.com");
    user.setSex(SexEnum.MAN); // 使用枚举值

    userMapper.insert(user);
}

当插入数据时,会将枚举值转换为1,也就是枚举类中的value属性值

9.乐观锁插件

当要更新一条记录的时候,希望这条记录没有被别人更新,就可以通过乐观锁来实现

乐观锁实现方式:

  • 取出记录时,获取当前version

  • 更新时,带上这个version

  • 执行更新时, set version = newVersion where version = oldVersion

  • 如果version不对,就更新失败

代码实现

package cn.it.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
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;

@Configuration
public class PageConfig {

    /**
     * 3.4.0之前的版本用这个
     * @return
     */
    
    /* 
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return  new PaginationInterceptor();
    }
    */

    /**
     * 3.4.0之后提供的拦截器的配置方式
     * @return
     */
   @Bean
   public MybatisPlusInterceptor mybatisPlusInterceptor(){
       MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
       mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
       mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 乐观锁插件
       return mybatisPlusInterceptor;
   }


}

第二步:修改表结构,添加version字段

ALTER TABLE `tb_user` ADD COLUMN `version` int(10) NULL;
UPDATE `tb_user` SET `version`='1'; 

第三步:修改实体类,添加version属性

@Version
private Integer version;

第四步:测试

@Test
public void testOptimisticLock() {
    User user = new User();
    user.setAge(30);
    user.setId(2L);
    user.setVersion(1); // 必须设置version

    int result = this.userMapper.updateById(user);
    System.out.println("result = " + result);
}

运行结果:

==>  Preparing: UPDATE tb_user SET age=?, version=? WHERE id=? AND version=?
==> Parameters: 30(Integer), 2(Integer), 2(Long), 1(Integer)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@73044cdf]
result = 1

不修改代码,再次运行,运行结果:

==>  Preparing: UPDATE tb_user SET age=?, version=? WHERE id=? AND version=?
==> Parameters: 30(Integer), 2(Integer), 2(Long), 1(Integer)
<==    Updates: 0
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@73044cdf]
result = 0

第一次运行时,更新的条件中有version条件,且和数据库version值一致,都为1,因此可以更新成功,并且将数据库中version设置为2。如果再次执行,更新则不成功。因为传入的version和数据库中的值并不一致,这样就避免了多人同时更新时导致数据的不一致。

10.service 封装

Mybatis-Plus 为了开发更加快捷,对业务层也进行了封装,直接提供了相关的接口和实现类。我们在进行业务层开发时,可以继承它提供的接口和实现类,使得编码更加高效。

步骤

  1. 定义接口继承IService

  2. 定义实现类继承ServiceImpl<Mapper,Entity> 实现定义的接口

定义Service接口

package cn.it.service;

import cn.it.pojo.User;
import com.baomidou.mybatisplus.extension.service.IService;

public interface UserService extends IService<User> {
    
}

定义Service实现类

package cn.it.service.impl;

import cn.it.dao.UserMapper;
import cn.it.pojo.User;
import cn.it.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
   /**
     * test
     */
    public void test(){
        // this.baseMapper可以获取到userMapper对象;
        UserMapper baseMapper = this.baseMapper;
    }
}

11. 代码生成器

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

11.1 导入依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.4.RELEASE</version>
</parent>

<dependencies>
   
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- mybatis plus 启动器-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.0</version>
    </dependency>

    <!--mp 代码生成器-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.4.0</version>
    </dependency>

    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
        <version>2.3.30</version>
    </dependency>

</dependencies>

11.2 main方法

// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {

    /**
     * <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");
        System.out.println(projectPath);
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("itheima");
        gc.setOpen(false);
        // gc.setSwagger2(true); 实体属性 Swagger2 注解
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql:///mp");
        // dsc.setSchemaName("public");
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        // 包前缀
        pc.setParent("com.itheima");
        pc.setModuleName(scanner("模块名"));
        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);
        //strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        // 公共父类
        //strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
        // 写于父类中的公共字段
        strategy.setSuperEntityColumns("id");
        strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix(pc.getModuleName() + "_");
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值