目录
[一、MyBatis-Plus 核心优势](#一、MyBatis-Plus 核心优势)
[二、MyBatis-Plus 核心组件](#二、MyBatis-Plus 核心组件)
[1. 核心接口 / 类](#1. 核心接口 / 类)
[2. 核心注解](#2. 核心注解)
[三、Spring Boot 集成 MyBatis-Plus 实战](#三、Spring Boot 集成 MyBatis-Plus 实战)
[1. 环境准备](#1. 环境准备)
[2. 代码实现](#2. 代码实现)
[(3)自定义字段填充处理器(处理 createTime/updateTime)](#(3)自定义字段填充处理器(处理 createTime/updateTime))
[(4)Mapper 接口(继承 BaseMapper)](#(4)Mapper 接口(继承 BaseMapper))
[(5)Service 层(通用 Service)](#(5)Service 层(通用 Service))
[① Service 接口(继承 IService)](#① Service 接口(继承 IService))
[② Service 实现类(继承 ServiceImpl)](#② Service 实现类(继承 ServiceImpl))
[3. 核心功能使用示例](#3. 核心功能使用示例)
[(1)通用 CRUD(Mapper 层)](#(1)通用 CRUD(Mapper 层))
(2)条件构造器(QueryWrapper/LambdaQueryWrapper)
[(4)通用 Service 层使用(批量操作、分页)](#(4)通用 Service 层使用(批量操作、分页))
[四、MyBatis-Plus 高级功能](#四、MyBatis-Plus 高级功能)
[1. 乐观锁插件(解决并发更新)](#1. 乐观锁插件(解决并发更新))
[2. 代码生成器(AutoGenerator)](#2. 代码生成器(AutoGenerator))
[3. 多数据源配置](#3. 多数据源配置)
[五、MyBatis-Plus 与 MyBatis 对比](#五、MyBatis-Plus 与 MyBatis 对比)
MyBatis-Plus(简称 MP)是基于 MyBatis 的增强工具,在 MyBatis 基础上只做增强不做改变,提供了大量开箱即用的功能(如通用 CRUD、分页、条件构造器等),彻底简化了 MyBatis 的开发,大幅减少重复的 SQL 编写工作。
一、MyBatis-Plus 核心优势
| 特性 | 说明 |
|---|---|
| 通用 CRUD | 内置 BaseMapper/IService,无需编写基础增删改查 SQL |
| 条件构造器 | 链式编程构建动态 SQL,替代 MyBatis 繁琐的 XML 动态标签 |
| 自动分页 | 内置分页插件,无需集成 PageHelper,分页查询更简单 |
| 代码生成器 | 一键生成 Entity、Mapper、Service、Controller 全套代码 |
| 主键生成策略 | 支持雪花算法、自增、UUID 等多种主键生成方式,无需手动配置 |
| 逻辑删除 | 自动处理逻辑删除(标记删除),无需手动写删除 SQL |
| 乐观锁 | 内置乐观锁插件,解决并发更新问题 |
| 多数据源 | 简单配置即可实现多数据源切换,无需复杂的代码改造 |
| 注解式开发 | 支持注解替代 XML,同时兼容 MyBatis 原有 XML 写法 |
二、MyBatis-Plus 核心组件
1. 核心接口 / 类
- BaseMapper<T>:通用 Mapper 接口,封装了单表 CRUD 操作,自定义 Mapper 继承即可使用。
- IService<T> / ServiceImpl<M,T>:通用 Service 层接口 / 实现,封装了批量操作、分页查询等高级 CRUD。
- QueryWrapper/LambdaQueryWrapper:条件构造器,用于动态构建 WHERE 条件(Lambda 版更优雅)。
- UpdateWrapper/LambdaUpdateWrapper:更新条件构造器,用于动态构建更新语句。
- Page<T>:分页对象,配合分页插件实现自动分页。
2. 核心注解
| 注解 | 作用 |
|---|---|
| @TableName | 映射数据库表名(实体类名与表名不一致时使用) |
| @TableId | 标记主键字段,指定主键生成策略(如 IdType.ASSIGN_ID 雪花算法) |
| @TableField | 映射数据库字段(字段名与属性名不一致、忽略字段、填充字段等) |
| @TableLogic | 标记逻辑删除字段(如 deleted=0 未删除,deleted=1 已删除) |
| @Version | 标记乐观锁字段(用于并发更新控制) |
| @TableFill | 标记自动填充字段(如创建时间、更新时间) |
三、Spring Boot 集成 MyBatis-Plus 实战
1. 环境准备
(1)依赖引入(Maven)
xml
<!-- Spring Boot 父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/>
</parent>
<dependencies>
<!-- MyBatis-Plus 核心依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.5</version> <!-- 最新稳定版 -->
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok(简化实体类) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring Boot 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
(2)核心配置(application.yml)
yaml
# 数据源配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp_demo?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8
username: root
password: 123456
# 连接池配置(默认 HikariCP)
hikari:
maximum-pool-size: 10
minimum-idle: 5
# MyBatis-Plus 配置
mybatis-plus:
# 实体类别名包
type-aliases-package: com.example.mp.entity
# Mapper XML 文件位置(如需保留 XML 写法)
mapper-locations: classpath:mapper/**/*.xml
# 全局配置
global-config:
db-config:
# 主键生成策略:雪花算法(分布式唯一ID)
id-type: assign_id
# 逻辑删除配置
logic-delete-field: deleted # 逻辑删除字段名
logic-delete-value: 1 # 已删除值
logic-not-delete-value: 0 # 未删除值
# 配置项(兼容 MyBatis 配置)
configuration:
map-underscore-to-camel-case: true # 自动下划线转驼峰(默认开启)
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印 SQL 日志
2. 代码实现
(1)数据库表设计
sql
CREATE DATABASE IF NOT EXISTS mp_demo;
USE mp_demo;
-- 用户表(含逻辑删除、自动填充字段)
CREATE TABLE `user` (
`id` BIGINT NOT NULL COMMENT '主键ID(雪花算法)',
`user_name` VARCHAR(50) NOT NULL COMMENT '用户名',
`age` INT COMMENT '年龄',
`email` VARCHAR(100) COMMENT '邮箱',
`deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除(0-未删,1-已删)',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) COMMENT '用户表';
(2)实体类(Entity)
java
运行
package com.example.mp.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("user") // 表名映射(实体名与表名一致时可省略)
public class User {
// 主键:雪花算法生成(IdType.ASSIGN_ID)
@TableId(type = IdType.ASSIGN_ID)
private Long id;
// 字段映射(属性名与字段名一致时可省略)
@TableField("user_name")
private String userName;
private Integer age;
private String email;
// 逻辑删除字段
@TableLogic
private Integer deleted;
// 自动填充字段:创建时间
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
// 自动填充字段:更新时间
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
(3)自定义字段填充处理器(处理 createTime/updateTime)
java
运行
package com.example.mp.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component // 必须交给 Spring 管理
public class MyMetaObjectHandler implements MetaObjectHandler {
// 插入时填充
@Override
public void insertFill(MetaObject metaObject) {
// 填充 createTime 和 updateTime
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
// 更新时填充
@Override
public void updateFill(MetaObject metaObject) {
// 只填充 updateTime
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
(4)Mapper 接口(继承 BaseMapper)
java
运行
package com.example.mp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mp.entity.User;
import org.apache.ibatis.annotations.Mapper;
// 无需编写任何方法,BaseMapper 已封装所有基础 CRUD
@Mapper // 或在启动类加 @MapperScan("com.example.mp.mapper")
public interface UserMapper extends BaseMapper<User> {
// 如需自定义 SQL,可在此编写(兼容 MyBatis 注解/XML 方式)
// 示例:自定义查询
// @Select("SELECT * FROM user WHERE user_name = #{userName}")
// List<User> selectByUserName(String userName);
}
(5)Service 层(通用 Service)
① Service 接口(继承 IService)
java
运行
package com.example.mp.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.mp.entity.User;
public interface UserService extends IService<User> {
// 如需自定义业务方法,在此扩展
}
② Service 实现类(继承 ServiceImpl)
java
运行
package com.example.mp.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mp.entity.User;
import com.example.mp.mapper.UserMapper;
import com.example.mp.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
// 通用 Service 方法已全部实现,无需编写代码
}
(6)启动类
java
运行
package com.example.mp;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// 批量扫描 Mapper 接口(替代每个 Mapper 加 @Mapper)
@MapperScan("com.example.mp.mapper")
@SpringBootApplication
public class MpDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MpDemoApplication.class, args);
}
}
3. 核心功能使用示例
(1)通用 CRUD(Mapper 层)
java
运行
package com.example.mp;
import com.example.mp.entity.User;
import com.example.mp.mapper.UserMapper;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class MapperCrudTest {
@Resource
private UserMapper userMapper;
// 新增
@Test
public void testInsert() {
User user = new User();
user.setUserName("张三");
user.setAge(25);
user.setEmail("zhangsan@example.com");
// insert 方法返回受影响行数
int rows = userMapper.insert(user);
System.out.println("新增行数:" + rows + ",用户ID:" + user.getId()); // 雪花算法生成ID
}
// 根据ID查询
@Test
public void testSelectById() {
User user = userMapper.selectById(176928745896704L);
System.out.println("查询结果:" + user);
}
// 查询所有
@Test
public void testSelectList() {
List<User> userList = userMapper.selectList(null); // null 表示无条件
userList.forEach(System.out::println);
}
// 根据ID更新
@Test
public void testUpdateById() {
User user = new User();
user.setId(176928745896704L);
user.setAge(26); // 只更新age字段
int rows = userMapper.updateById(user);
System.out.println("更新行数:" + rows);
}
// 根据ID删除(逻辑删除)
@Test
public void testDeleteById() {
int rows = userMapper.deleteById(176928745896704L);
System.out.println("删除行数:" + rows); // 实际执行 UPDATE user SET deleted=1 WHERE id=?
}
}
(2)条件构造器(QueryWrapper/LambdaQueryWrapper)
java
运行
@Test
public void testQueryWrapper() {
// 1. 普通 QueryWrapper(需手动写字段名,易出错)
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("age", 25) // 等于
.like("user_name", "张") // 模糊查询
.orderByDesc("create_time"); // 排序
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println("普通条件查询:" + userList);
// 2. LambdaQueryWrapper(类型安全,推荐)
LambdaQueryWrapper<User> lambdaQuery = new LambdaQueryWrapper<>();
lambdaQuery.eq(User::getAge, 25)
.like(User::getUserName, "张")
.orderByDesc(User::getCreateTime);
List<User> lambdaList = userMapper.selectList(lambdaQuery);
System.out.println("Lambda条件查询:" + lambdaList);
}
(3)自动分页查询
java
运行
@Test
public void testPage() {
// 1. 构建分页对象(第1页,每页10条)
Page<User> page = new Page<>(1, 10);
// 2. 分页查询(条件为null表示无条件)
Page<User> resultPage = userMapper.selectPage(page, null);
// 3. 分页结果解析
System.out.println("总条数:" + resultPage.getTotal());
System.out.println("总页数:" + resultPage.getPages());
System.out.println("当前页数据:" + resultPage.getRecords());
System.out.println("当前页码:" + resultPage.getCurrent());
System.out.println("每页条数:" + resultPage.getSize());
}
// 自定义SQL分页(如需自定义查询)
// 1. Mapper 接口添加方法
// Page<User> selectUserPage(Page<User> page, @Param("ew") LambdaQueryWrapper<User> queryWrapper);
// 2. XML 编写 SQL(无需写 LIMIT,MP 自动拼接)
// <select id="selectUserPage" resultType="User">
// SELECT * FROM user ${ew.customSqlSegment}
// </select>
// 3. 调用
// Page<User> page = new Page<>(1, 10);
// LambdaQueryWrapper<User> query = new LambdaQueryWrapper<>().gt(User::getAge, 20);
// Page<User> result = userMapper.selectUserPage(page, query);
(4)通用 Service 层使用(批量操作、分页)
java
运行
package com.example.mp;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.mp.entity.User;
import com.example.mp.service.UserService;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
import java.util.List;
@SpringBootTest
public class ServiceCrudTest {
@Resource
private UserService userService;
// 批量新增
@Test
public void testSaveBatch() {
User user1 = new User();
user1.setUserName("李四");
user1.setAge(24);
User user2 = new User();
user2.setUserName("王五");
user2.setAge(26);
boolean success = userService.saveBatch(Arrays.asList(user1, user2));
System.out.println("批量新增是否成功:" + success);
}
// 分页查询(Service 层)
@Test
public void testServicePage() {
Page<User> page = new Page<>(1, 10);
LambdaQueryWrapper<User> query = new LambdaQueryWrapper<>().gt(User::getAge, 20);
IPage<User> resultPage = userService.page(page, query);
System.out.println("Service分页总条数:" + resultPage.getTotal());
}
// 批量删除
@Test
public void testRemoveBatchByIds() {
boolean success = userService.removeBatchByIds(Arrays.asList(176928745896704L, 176928745896705L));
System.out.println("批量删除是否成功:" + success);
}
// 条件查询单个结果
@Test
public void testGetOne() {
LambdaQueryWrapper<User> query = new LambdaQueryWrapper<>().eq(User::getUserName, "张三");
User user = userService.getOne(query, false); // false 表示不抛出多条结果异常
System.out.println("单个结果:" + user);
}
}
四、MyBatis-Plus 高级功能
1. 乐观锁插件(解决并发更新)
(1)添加乐观锁字段
sql
ALTER TABLE `user` ADD COLUMN `version` INT DEFAULT 1 COMMENT '乐观锁版本号';
(2)实体类添加注解
java
运行
@Version // 标记乐观锁字段
private Integer version;
(3)配置乐观锁插件
java
运行
package com.example.mp.config;
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;
@Configuration
public class MyBatisPlusConfig {
// 配置插件(分页 + 乐观锁)
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
// 乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
(4)使用示例
java
运行
@Test
public void testOptimisticLocker() {
// 1. 查询用户(获取当前版本号)
User user = userMapper.selectById(176928745896704L);
// 2. 更新用户
user.setAge(27);
int rows = userMapper.updateById(user);
// 并发场景下,若版本号不匹配,rows=0(更新失败)
System.out.println("更新行数:" + rows);
}
2. 代码生成器(AutoGenerator)
MP 提供了强大的代码生成器,可一键生成全套代码,减少重复劳动。
(1)引入代码生成器依赖
xml
<!-- MyBatis-Plus 代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.5</version>
</dependency>
<!-- 模板引擎(默认 Velocity) -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
(2)生成代码示例
java
运行
package com.example.mp;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import java.util.Collections;
public class CodeGenerator {
public static void main(String[] args) {
// 数据源配置
String url = "jdbc:mysql://localhost:3306/mp_demo?useSSL=false&serverTimezone=Asia/Shanghai";
String username = "root";
String password = "123456";
// 快速生成代码
FastAutoGenerator.create(url, username, password)
// 全局配置
.globalConfig(builder -> {
builder.author("mp-demo") // 设置作者
.outputDir(System.getProperty("user.dir") + "/src/main/java") // 输出目录
.enableSwagger() // 开启 Swagger(如需)
.commentDate("yyyy-MM-dd") // 注释日期格式
.disableOpenDir(); // 生成后不打开目录
})
// 包配置
.packageConfig(builder -> {
builder.parent("com.example.mp") // 父包名
.moduleName("") // 模块名(无则空)
.entity("entity") // 实体类包名
.mapper("mapper") // Mapper 包名
.service("service") // Service 包名
.controller("controller") // Controller 包名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml,
System.getProperty("user.dir") + "/src/main/resources/mapper")); // Mapper XML 路径
})
// 策略配置
.strategyConfig(builder -> {
builder.addInclude("user") // 生成指定表(多个表用逗号分隔)
.addTablePrefix("t_", "sys_") // 过滤表前缀(如 t_user → User)
// 实体类策略
.entityBuilder()
.enableLombok() // 开启 Lombok
.enableTableFieldAnnotation() // 生成字段注解
.idType(com.baomidou.mybatisplus.annotation.IdType.ASSIGN_ID) // 主键策略
// Mapper 策略
.mapperBuilder()
.enableBaseResultMap() // 生成 BaseResultMap
.enableBaseColumnList() // 生成 BaseColumnList
// Service 策略
.serviceBuilder()
.formatServiceFileName("%sService") // Service 命名格式
.formatServiceImplFileName("%sServiceImpl") // ServiceImpl 命名格式
// Controller 策略
.controllerBuilder()
.enableRestStyle(); // 开启 RestController 风格
})
// 执行生成
.execute();
}
}
3. 多数据源配置
MP 支持简单配置实现多数据源,适用于读写分离、分库等场景。
(1)引入多数据源依赖
xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.6.1</version>
</dependency>
(2)配置多数据源(application.yml)
yaml
spring:
datasource:
dynamic:
primary: master # 默认数据源
strict: false # 关闭严格模式
datasource:
# 主库
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp_demo_master?useSSL=false
username: root
password: 123456
# 从库
slave:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp_demo_slave?useSSL=false
username: root
password: 123456
(3)使用多数据源(注解指定)
java
运行
// Service 层指定数据源
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
// 主库(默认)
public List<User> selectMaster() {
return baseMapper.selectList(null);
}
// 从库
@DS("slave") // 指定从库数据源
public List<User> selectSlave() {
return baseMapper.selectList(null);
}
}
五、MyBatis-Plus 与 MyBatis 对比
| 维度 | MyBatis | MyBatis-Plus |
|---|---|---|
| 基础 CRUD | 需手动编写 XML / 注解 SQL | 继承 BaseMapper/IService 直接用 |
| 动态 SQL | XML 标签(if/where/foreach) | 条件构造器(链式编程) |
| 分页 | 需集成 PageHelper | 内置分页插件,一键分页 |
| 主键生成 | 需手动配置 | 内置多种策略(雪花算法 / 自增等) |
| 逻辑删除 | 需手动写 SQL | 注解 + 自动处理 |
| 代码生成 | 无原生支持 | 一键生成全套代码 |
| 兼容性 | 原生 MyBatis 语法 | 完全兼容 MyBatis,可混用 XML / 注解 |
六、最佳实践
- 优先使用 Lambda 条件构造器:避免硬编码字段名,减少拼写错误。
- 通用 CRUD 用 MP,复杂 SQL 用 XML:简单操作依赖 MP 通用方法,复杂关联查询仍用 MyBatis XML 更清晰。
- 合理使用逻辑删除:避免物理删除数据,便于数据恢复和审计。
- 乐观锁用于并发更新:如库存扣减、订单状态更新等场景。
- 代码生成器提升效率:新项目初始化时,用代码生成器一键生成基础代码。
- 分页查询必用 Page 对象:避免手动拼接 LIMIT,MP 自动适配不同数据库方言。
- 字段自动填充统一处理:创建时间、更新时间等字段通过填充处理器统一管理,避免重复代码。
七、总结
MyBatis-Plus 是 MyBatis 的 "黄金搭档",在保留 MyBatis 灵活性的同时,大幅降低了开发成本:
- 核心价值:通用 CRUD 省去 80% 重复 SQL 编写,条件构造器简化动态 SQL,内置功能覆盖大部分业务场景。
- Spring Boot 集成:仅需引入依赖 + 简单配置,即可快速使用所有增强功能,完全兼容 MyBatis 原有代码。
- 适用场景:中小项目可完全基于 MP 开发,大型项目可混合使用 MP 通用方法 + MyBatis 复杂 SQL,兼顾效率与灵活性。
掌握 MyBatis-Plus 的关键是理解通用 CRUD 接口 和条件构造器,在此基础上结合分页、乐观锁、代码生成器等高级功能,可极大提升开发效率。