MyBatis-Plus 学习记录

MyBatis-Plus

官网👉 ​MyBatis-Plus (baomidou.com)

GitHub 👉 https://github.com/baomidou/mybatis-plus

framework

特性

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

开始

新建SpringBoot项目

1️⃣ 新建项目 Create New Project

2️⃣ 选择 Spring Initializr 然后 Next ⚠️ 如果没有该选项,请下载Spring Boot 插件并启用

3️⃣ Type 选择 Maven Project ​

🆗

添加Maven依赖

pom.xml

<?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.7.5</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.learn</groupId>
	<artifactId>mybatisplus</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>learnMyBatisPlus</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.12</version>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.27</version>
			<scope>runtime</scope>
		</dependency>


	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Spring配置文件

application.properties

spring.datasource.driver-class-name:com.mysql.cj.jdbc.Driver
spring.datasource.url: jdbc:mysql://xxx
spring.datasource.username: xxx
spring.datasource.password: xxx

测试

数据库表名为user

@Data
public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer roleid;
}
public interface UserMapper extends BaseMapper<User> {
}
@SpringBootTest
public class MyBatisPlusTests {
    @Resource
    private UserMapper userMapper;

    @Test
    public void test01() {
        List<User> list = userMapper.selectList(null);
        list.forEach(System.out::println);
    }
}

实体与表的映射@TableName/table-prefix

  • 使用注解@TableName指定实体所对应的表
@Data
@TableName("t_user")
public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer roleid;
}
  • 全局配置表明统一前缀
mybatis-plus.global-config.db-config.table-prefix=t_

声明主键@TableId

mybatis默认主键为id

修改默认主键为类属性名uid,这样mybatisplus执行sql语句时,不再是 如select id ... 而是 select uid ...

@Data
public class User {
    @TableId
    private Integer uid;
    private String username;
    private String password;
    private Integer roleid;
}

xxx为数据库表列名

@Data
public class User {
    @TableId("xxx")
    private Integer id;
    private String username;
    private String password;
    private Integer roleid;
}

ID自增 IdType.AUTO/id-type

⚠️使用mybatisplus的id自动生成算法是,手动设置id无效

  • type = IdType.AUTO

前提 数据库该表主键是自增的,否则无效

@Data
public class User {
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private String username;
    private String password;
    private Integer roleid;
}
  • 全局配置
mybatis-plus.global-config.db-config.id-type=auto

声明字段映射 @TableField

表列名 u_name 对应 类属性名 username

@Data
public class User {
    private Integer id;
    @TableField("u_name")
    private String username;
    private String password;
    private Integer roleid;
}

逻辑删除 @TableLogic

  • 携带此注解的类,执行查询语句时查询该值为0的数据

@TableLogic把对应字段做修改(设置成1)

  • isDeleted : 1 -> 已删除

  • isDeleted :0 -> 未删除(逻辑)

@Data
public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer roleid;
    @TableLogic
    private Integer isDeleted;
}

BaseMapper

Wrapper

QueryWrapper

  • QueryWrapper select(String... columns)

查询指定列

queryWrapper.select("username","roleid");
  • Children inSql(R column, String inValue)

效果 SELECT * FROM t_user WHERE column IN (inValue)

queryWrapper.inSql("id", "SELECT * FROM t_user WHERE `roleid` = 1");

UpdateWrapper

  • Children set(R column, Object val)
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.isNotNull("username")
    .eq("roleid", 3)
    .or()
    .eq("username", "admin");
updateWrapper.set("username", "u000x").set("roleid", 1);
userMapper.update(null, updateWrapper); 

LambdaQueryWrapper

防止写错列名...User::getUsername获取到列名,不再手写

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.like(User::getUsername, "aa")
        .gt(User::getRoleid, 3);
userMapper.selectList(lambdaQueryWrapper);

LambdaUpdateWrapper

防止写错列名...User::getUsername获取到列名,不再手写

LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.isNotNull(User::getUsername)
        .eq(User::getRoleid, 3)
        .or()
        .eq(User::getUsername, "admin");
lambdaUpdateWrapper.set(User::getUsername, "u000x").set(User::getRoleid, 1);
userMapper.update(null, lambdaUpdateWrapper);

组装条件

  • 组装前
String username = "a";
Integer roleid = 0;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();

if (StringUtils.isNotBlank(username))
    queryWrapper.like("username", username);
if (roleid != null)
    queryWrapper.lt("roleid", roleid);

userMapper.selectList(queryWrapper);
  • 组装后
String username = "a";
Integer roleid = 0;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();

queryWrapper.like(StringUtils.isNotBlank(username), "username", username);
queryWrapper.like(roleid != null, "roleid", roleid);

userMapper.selectList(queryWrapper);

插入

  • int insert(T entity);
public void testInsert() {
    User user = new User();
    user.setUsername("testInsert");
    user.setPassword("123456");
    user.setRoleid(2);
    int i = userMapper.insert(user);
    System.out.println("before insert   ==> : " + user);
    System.out.println("userMapper.insert result ==> : " + i);
    System.out.println("after insert    ==> : " + user);
}
==>  Preparing: INSERT INTO user ( id, username, password, roleid ) VALUES ( ?, ?, ?, ? )
==> Parameters: 1673330689(Integer), testInsert(String), 123456(String), 2(Integer)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@771cbb1a]
before insert   ==> : User(id=1673330689, username=testInsert, password=123456, roleid=2)
userMapper.insert result ==> : 1
after insert    ==> : User(id=1673330689, username=testInsert, password=123456, roleid=2)

mybatis-plus根据算法自动生成id

删除

  • int deleteById(Serializable id);
userMapper.deleteById(1052631042);
  • int deleteByMap(@Param("cm") Map<String, Object> columnMap)
HashMap<String, Object> map = new HashMap<>();
map.put("username", "zhangsan");
map.put("rolid", 2);
userMapper.deleteByMap(map);
  • int deleteBatchIds
List<Integer> idList = Arrays.asList(1, 2, 3);
userMapper.deleteBatchIds(idList);
  • int delete(@Param("ew") Wrapper queryWrapper);
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("roleid", 3)
        .isNotNull("username");

userMapper.delete(wrapper);

更新

  • int updateById(@Param("et") T entity);
User user = new User();
user.setId(1);
user.setRoleid(3);
userMapper.updateById(user);
  • int update(@Param("et") T entity, @Param("ew") Wrapper updateWrapper);
User user = new User();
user.setUsername("admin");
user.setPassword("123456");
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("zhangsan", "123")
    .gt("roleid", 3)
    .or()
    .lt("roleid", 1);
userMapper.update(user,updateWrapper);// 使用updateWrapper.set 等更新动作时 第一个参数应为null 详见UpdateWrapper

查询

  • T selectById(Serializable id);
userMapper.selectById(1);
  • List selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
List<Integer> idList = Arrays.asList(1, 2, 3);
userMapper.selectBatchIds(idList);
  • List selectByMap(@Param("cm") Map<String, Object> columnMap);
HashMap<String, Object> map = new HashMap<>();
map.put("username", null);
userMapper.selectByMap(map);
  • default T selectOne(@Param("ew") Wrapper queryWrapper)
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.isNull("username");
userMapper.selectOne(wrapper);
  • boolean exists(Wrapper queryWrapper)
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.isNull("username");
userMapper.exists(wrapper);
  • Long selectCount(@Param("ew") Wrapper queryWrapper);

  • List selectList(@Param("ew") Wrapper queryWrapper)

  • List<Map<String, Object>> selectMaps(@Param("ew") Wrapper queryWrapper);

// 查出指定列到map
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("username","roleid");
userMapper.selectMaps(queryWrapper);
  • List<Object.> selectObjs(@Param("ew") Wrapper<T.> queryWrapper);

  • <.P extends IPage<T.>> P selectPage(P page, @Param("ew") Wrapper<T.> queryWrapper);

  • <.P extends IPage<Map<String, Object>>> P selectMapsPage(P page, @Param("ew") Wrapper<T.> queryWrapper);

自定义SQL

  • 使用注解
@Select("select username,roleid from user where id = #{id}")
Map<String,Object> selectMapById(@Param("id") Integer id);
  • 使用xml

与mybatis一致,但是需要声明位置,以下是默认位置

mybatis-plus.mapper-locations=

高优先级查询 Lambda

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
// Consumer<Param> Param是当前条件构造器
// 优先执行lambda表达式内容
queryWrapper.isNotNull("username").and(i -> {
    // i 是当前条件构造器
    i.isNull("password")
        .or()
        .eq("username", "admin");
});
public interface Nested<Param, Children> extends Serializable {
    default Children and(Consumer<Param> consumer) {
        return this.and(true, consumer);
    }
    ...
}
@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

Service CRUD 接口介绍

说明:

  • 通用 Service CRUD 封装 IService 接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,
  • 泛型 T 为任意实体对象
  • 建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承 Mybatis-Plus 提供的基类
  • 对象 Wrapper条件构造器

interface IService<T.>

T为实体类

class ServiceImpl<M extends BaseMapper<T.>, T> implements IService<T.>

  • M --> Mapper接口
  • T --> 实体类

Service 拓展

  • 在自带的Service上拓展

接口

public interface UserService extends IService<User> {
}

接口实现

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

}

Service 使用

查询

long l = userService.count();
System.out.println("count   ==>   " + l);

添加

ArrayList<User> list = new ArrayList<>();
...
list.add(user1);
list.add(user2);
list.add(user3);
boolean b = userService.saveBatch(list);

saveOrUpdate有id -> 修改,无id -> 添加

雪花算法

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

了解更多 👉 什么是雪花算法? - 袁子弹 - 博客园 (cnblogs.com)

  • 背景
    需要选择合适的方案去应对数据规模的增长,以应对逐渐增长的访问压力和数据量。数据库的扩展方式主要包括:业务分库、主从复制,数据库分表。
  • 数据库分表
    将不同业务数据分散存储到不同的数据库服务器,能够支撑百万甚至千万用户规模的业务,但如果业务继续发展,同一业务的单表数据也会达到单台数据库服务器的处理瓶颈。例如,淘宝的几亿用户数据,如果全部存放在-台数据库服务器的一-张表中,肯定是无法满足性能要求的,此时就需要对单表数据进行拆分。
    单表数据拆分有两种方式:垂直分表和水平分表。

分页插件

配置文件

@Configuration
//扫描mapper包下的接口
@MapperScan("com.learn.mybatisplus.mapper")
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

        return mybatisPlusInterceptor;
    }
}

Page

Page属性

protected List<T> records; // 当前页数据
protected long total;// 总记录数
protected long size;
protected long current;
protected List<OrderItem> orders; // 排序字段信息
protected boolean optimizeCountSql;
protected boolean searchCount;
protected boolean optimizeJoinOfCountSql;
protected String countId;
protected Long maxLimit;

Test

// 第几页 每页多长
Page<User> page = new Page<>(1, 3);
userMapper.selectPage(page, null);// 这样page 就有东西了 ,第二个参数是查询条件,QueryWrapper
System.out.println("getPages ==> " + page.getPages());
System.out.println("getCurrent ==> " + page.getCurrent());
System.out.println("getSize ==> " + page.getSize());
System.out.println("getRecords ==> " + page.getRecords());
System.out.println("getTotal ==> " + page.getTotal());
System.out.println("hasNext ==> " + page.hasNext());
System.out.println("hasPrevious ==> " + page.hasPrevious());
System.out.println("optimizeCountSql ==> " + page.optimizeCountSql());
System.out.println("optimizeJoinOfCountSql ==> " + page.optimizeJoinOfCountSql());
System.out.println("searchCount ==> " + page.searchCount());
System.out.println("maxLimit ==> " + page.maxLimit());
System.out.println("getOrders ==> " + page.getOrders());// Deprecated
System.out.println("isOptimizeCountSql ==> " + page.isOptimizeCountSql());// Deprecated
System.out.println("isSearchCount ==> " + page.isSearchCount());// Deprecated
System.out.println("getCountId ==> " + page.getCountId());// Deprecated

Console

getPages ==> 3 // 页总数
getCurrent ==> 1 // 当前页码
getSize ==> 3 // 本页数据条数
getRecords ==> [User(id=1, username=zhangsan1, password=123, roleid=1), User(id=2, username=zhangsan2, password=123, roleid=1), User(id=3, username=zhangsan3, password=123, roleid=3)]
getTotal ==> 7 // 该表记录数 受searchCount影响
hasNext ==> true
hasPrevious ==> false
optimizeCountSql ==> true // 自动优化 COUNT SQL
optimizeJoinOfCountSql ==> true // 优化计数Sql的连接
searchCount ==> true // 是否进行 count 查询
maxLimit ==> null // 单页分页条数限制,默认无限制。
getOrders ==> [] // 排序字段后的信息 Deprecated
isOptimizeCountSql ==> true // 自动优化 COUNT SQL Deprecated
isSearchCount ==> true //  Deprecated
getCountId ==> null // Deprecated

乐观锁与悲观锁

并发时防止出现脏数据,

场景:

A先拿到x=10准备进行x-1操作

A拿到x并在更新x前B拿到了x=10,将x+1

B先完成x+1

最后x=10,本应该是先x-1再x+1

解决:加锁,A拿到x时B排队等候

乐观锁更新时进行检查版本等(检查是否被修改过)

悲观锁是该表正在被使用时,其他操作者只能等待操作完成

MyBatis-Plus的乐观锁

配置文件 @Bean MybatisPlusInterceptor

mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());// 添加乐观锁插件

添加字段version 并使用 @Version 注解

@Data
public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer roleid;
    @Version
    private Integer version;
}

通用枚举

枚举添加@EnumValue,不然添加的时候默认放的字符,现在可以指定那个属性放到数据库

@Getter
public enum SexEnum {
    MALE(1,"男"),
    FEMALE(2,"女");
    @EnumValue
    private Integer sex;
    private String sexName;

    SexEnum(Integer sex, String sexName) {
        this.sex = sex;
        this.sexName = sexName;
    }
}
@Data
public class User {
    private Integer id;
    @EnumValue
    private SexEnum sex;
    private String username;
    private String password;
    private Integer roleid;
}
# 扫描通用枚举
mybatis-plus.type-enums-package=com.learn.mybatisplus.enums
@Test
public void test07(){
    // 通用枚举
    User user = new User();
    user.setSex(SexEnum.FEMALE);
}

代码生成器

添加代码生成器核心和模板模板引擎依赖

pom.xml

<dependency>
   <groupId>com.baomidou</groupId>
   <artifactId>mybatis-plus-generator</artifactId>
   <version>3.5.1</version>
</dependency>

<dependency>
   <groupId>org.freemarker</groupId>
   <artifactId>freemarker</artifactId>
   <version>2.3.28</version>
</dependency>
public static void main(String[] args) {

    FastAutoGenerator.create("jdbc:mysql://", "username", "password")// 创建连接
            .globalConfig(builder -> {// 全局配置
                builder.author("ctp") // 作者
                        // .enableSwagger()// swagger 模式
                        .fileOverride() // 覆盖生成文件
                        .outputDir("E://mybatis_plus_out"); // 输出目录
            })
            .packageConfig(builder -> {// 设置包
                builder.parent("com.learn.mybatisplus") //父包名
                        //.moduleName("mybatisplus")//设置父包模块名  生成的包全在这里
                        .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "E://mybatis_plus_out"));// 映射文件生成路径
            })
            .strategyConfig(builder -> { // 策略配置
                builder.addInclude("t_user")// 需要逆向生成的表名
                        .addTablePrefix("t_");//设置过滤表前缀

            })
            .templateEngine(new FreemarkerTemplateEngine())// 使用freemarker模板引擎
            .execute();
}

多数据源

pom.xml

<dependency>
   <groupId>com.baomidou</groupId>
   <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
   <version>3.5.0</version>
</dependency>
# 多数据源
# primary数据源 必须在下面定义 spring.datasource.dynamic.datasource.master
# 可以自由定义spring.datasource.dynamic.primary=xxx时就必须存在spring.datasource.dynamic.datasource.xxx
spring.datasource.dynamic.primary=master
# 严格匹配数据源,默认false. true未匹配到指定数据源(找不到该数据库)时抛异常, false使用默认数据源(找不到时使用默认,不报错)
spring.datasource.dynamic.strict=false
spring.datasource.dynamic.datasource.master.url=jdbc:mysql://
spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.dynamic.datasource.master.username=
spring.datasource.dynamic.datasource.master.password=
spring.datasource.dynamic.datasource.db_sims.url=
spring.datasource.dynamic.datasource.db_sims.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.dynamic.datasource.db_sims.username=
spring.datasource.dynamic.datasource.db_sims.password=
# 日志输出 StdOutImpl是自带的
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus.global-config.db-config.table-prefix=t_
mybatis-plus.global-config.db-config.id-type=auto
public interface UserService extends IService<User> {
}
public interface SIMSUserService extends IService<SIMSUser> {
}
@DS("master")
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
@DS("db_sims")
@Service
public class SIMSUserServiceImpl extends ServiceImpl<SIMSUserMapper, SIMSUser> implements SIMSUserService {
}
@TableName("tb_user")
@Data
public class SIMSUser {
    @TableId("userid")
    private Integer id;
    @TableField("username")
    private String name;
    // ...
}
@Data
public class User {
    private Integer id;
    private String username;
    // ...
}
System.out.println(userService.getById(1));
System.out.println(simsUserService.getById(1));

MyBatisX

MyBatis-Plus为我们提供了强大的mapper和service模板,能够大大的提高开发效率但是在真正开发过程中,MyBatis-Plus并不能为我们解决所有问题,例如一些复杂的SQL,多表联查,我们就需要自己去编写代码和SQL语句,我们该如何快速的解决这个问题呢,这个时候可以使用MyBatisX插件MyBatisX-款基于IDEA的快速开发插件,为效率而生。

IDEA插件搜索MyBatisX安装启用并重启

接口与xml映射文件可以相互跳转

MyBatisX的功能需要IDEA先连接数据库才能使用

选中表让后选生成器

生成实体类信息选项

  • module path:模块,点击输入框弹出当前模块,选中即可
  • base package:例如com.learn
  • base path:包所在的base路径
  • superClass:父类
  • relative package:存实体的包,如entity或model或bean
  • ignore field prefix/suffix: 忽略字段的前/后缀
  • ignore table prefix/suffix:忽略表的前/后缀

生成Service、Mapper等文件信息选项

  • annotation:使用的MyBatis-Plus版本
  • options:生成的各个组件的选项
    • comment:注释
    • toString/hashCode/equals:选择Lombok这个就不选
    • Lombok:生成setter/getter等
  • template:选择版本模板格式
  • mapperInterface:mapper接口生成的位置
  • mapperXML:映射文件生成的位置
  • serviceImpl:业务实现类生成的位置
  • serviceInterface:业务接口生成的位置

点击Finsh即可生成

快速生成CURD

alt + Enter

选中,对应xml映射文件自动生成代码

根据方法名设置参数

learn from https://www.bilibili.com/video/BV12R4y157Be

posted @ 2022-11-12 14:27  夏末秋初~  阅读(28)  评论(0编辑  收藏  举报