外观
Spring Boot 4 MyBatis-Flex 实战
约 1393 字大约 5 分钟
Spring Boot 4MyBatis-FlexORM数据库
次阅读
2026-04-09
MyBatis-Flex 简介
MyBatis-Flex 是一个 MyBatis 增强框架,类比 MyBatis-Plus,但更轻量、性能更高。核心特点:
- 零第三方依赖:除 MyBatis 本身外无任何第三方依赖
- QueryWrapper:类型安全的查询构建器,支持 Lambda 表达式
- 高性能:查询构建无反射开销,基础 CRUD 性能接近手写 JDBC
- 代码生成器:支持生成 Entity、Mapper、Service、Controller
- 功能丰富:数据脱敏、逻辑删除、乐观锁、数据审计、数据填充、多数据源、ActiveRecord、关联查询
MyBatis-Flex vs MyBatis-Plus
| 对比项 | MyBatis-Plus | MyBatis-Flex |
|---|---|---|
| 第三方依赖 | 较多 | 零依赖 |
| QueryWrapper | 字符串列名,无编译检查 | Lambda 类型安全 |
| 性能 | 有反射开销 | 接近原生 JDBC |
| 多主键支持 | 有限 | 灵活(自增、雪花、UUID等) |
| Spring Boot 4 支持 | 暂无专用 starter | mybatis-flex-spring-boot4-starter |
Spring Boot 4 专用 Starter
MyBatis-Flex 从 v1.11.5(2025-12-24)开始提供 Spring Boot 4 专用 starter,当前最新版为 v1.11.6。
依赖配置
<!-- Spring Boot 4 专用 starter(注意:不是 mybatis-flex-spring-boot-starter) -->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot4-starter</artifactId>
<version>1.11.6</version>
</dependency>
<!-- 数据库驱动(以 MySQL 为例) -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 连接池(Spring Boot 默认 HikariCP) -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<!-- 代码生成器(可选) -->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-codegen</artifactId>
<version>1.11.6</version>
</dependency>重要:Spring Boot 4 项目必须使用
mybatis-flex-spring-boot4-starter,而不是mybatis-flex-spring-boot-starter。后者只支持 Spring Boot 3.x。
application.yml 配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-flex:
# Mapper XML 文件位置
mapper-locations: classpath*:/mapper/**/*.xml
# 实体类扫描路径
type-packages: com.example.entity
# 配置
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 全局配置
global-config:
# 逻辑删除配置
logic-delete-column: is_deleted
logic-delete-value: 1
logic-not-delete-value: 0
# 关键字列
key-config:
key-type: auto核心功能实战
Entity 定义
@Table("tb_account")
public class Account {
@Id(keyType = KeyType.Auto) // 自增主键
private Long id;
private String userName;
private Integer age;
private Date birthday;
@Column(isLogicDelete = true) // 逻辑删除字段
private Boolean isDeleted;
@Column(onUpdateValue = "now()") // 自动填充更新时间
private Date updateTime;
@Column(onInsertValue = "now()") // 自动填充创建时间
private Date createTime;
// getter/setter ...
}Mapper 接口
public interface AccountMapper extends BaseMapper<Account> {
// BaseMapper 已提供常用 CRUD 方法
// 如需自定义 SQL,可在此添加并在 XML 中实现
}查询操作(QueryWrapper)
MyBatis-Flex 的 QueryWrapper 是类型安全的,使用 Lambda 表达式引用列名:
// 基础查询
QueryWrapper query = QueryWrapper.create()
.select()
.from(ACCOUNT)
.where(ACCOUNT.AGE.ge(18))
.and(ACCOUNT.USER_NAME.like("张"))
.orderBy(ACCOUNT.ID.desc());
List<Account> accounts = accountMapper.selectListByQuery(query);
// 等价 SQL:
// SELECT * FROM tb_account
// WHERE age >= 18 AND user_name LIKE '%张%'
// ORDER BY id DESC// 条件构造(动态条件)
QueryWrapper query = QueryWrapper.create()
.select(ACCOUNT.ID, ACCOUNT.USER_NAME)
.from(ACCOUNT)
.where(ACCOUNT.AGE.ge(18))
.and(age != null ? ACCOUNT.AGE.le(age) : noCondition())
.and(userName != null ? ACCOUNT.USER_NAME.like(userName) : noCondition());CRUD 操作
@Service
public class AccountService {
@Autowired
private AccountMapper accountMapper;
// 新增
public void add(Account account) {
accountMapper.insert(account);
}
// 批量新增
public void batchAdd(List<Account> accounts) {
accountMapper.insertBatch(accounts);
}
// 根据ID查询
public Account getById(Long id) {
return accountMapper.selectOneById(id);
}
// 更新
public void update(Account account) {
accountMapper.update(account);
}
// 根据条件更新
public void updateByCondition() {
Account account = new Account();
account.setAge(20);
accountMapper.updateByCondition(account,
QueryWrapper.create().where(ACCOUNT.USER_NAME.like("test")));
}
// 删除
public void deleteById(Long id) {
accountMapper.deleteById(id); // 逻辑删除会自动处理
}
// 分页查询
public Page<Account> page(int pageNum, int pageSize) {
QueryWrapper query = QueryWrapper.create()
.from(ACCOUNT)
.orderBy(ACCOUNT.ID.desc());
return accountMapper.paginate(query, pageNum, pageSize);
}
}关联查询
@Table("tb_account")
public class Account {
@Id(keyType = KeyType.Auto)
private Long id;
private String userName;
// 一对一关联
@RelationOneToOne(selfField = "id", targetField = "accountId")
private AccountDetail detail;
// 一对多关联
@RelationOneToMany(selfField = "id", targetField = "accountId")
private List<Order> orders;
// 多对多关联
@RelationManyToMany(
selfField = "id",
targetField = "id",
joinTable = "tb_account_role",
joinSelfColumn = "account_id",
joinTargetColumn = "role_id"
)
private List<Role> roles;
}使用关联查询:
// 查询时自动加载关联数据
List<Account> accounts = accountMapper.selectListWithRelationsByQuery(
QueryWrapper.create().where(ACCOUNT.AGE.ge(18))
);ActiveRecord 模式
让 Entity 继承 Model 即可使用:
@Table("tb_account")
public class Account extends Model<Account> {
@Id(keyType = KeyType.Auto)
private Long id;
private String userName;
private Integer age;
// getter/setter ...
}
// 直接使用 Entity 操作
Account account = new Account();
account.setUserName("test");
account.setAge(20);
account.save(); // 新增
account = Account.getById(1L); // 查询
account.setAge(21);
account.updateById(); // 更新
account.deleteById(); // 删除多数据源配置
@Configuration
public class DataSourceConfig {
@Bean
@Primary
public DataSource masterDataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:mysql://localhost:3306/master_db");
ds.setUsername("root");
ds.setPassword("password");
return ds;
}
@Bean
public DataSource slaveDataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:mysql://localhost:3306/slave_db");
ds.setUsername("root");
ds.setPassword("password");
return ds;
}
}使用 @DS 注解切换数据源:
@DS("slave")
public List<Account> getFromSlave() {
return accountMapper.selectAll();
}数据脱敏
@Table("tb_account")
public class Account {
@Id(keyType = KeyType.Auto)
private Long id;
// 手机号脱敏:138****1234
@Column(typeHandler = DesensitizeTypeHandler.class)
@Desensitize(type = DesensitizeType.MOBILE)
private String phone;
// 邮箱脱敏:t***@example.com
@Column(typeHandler = DesensitizeTypeHandler.class)
@Desensitize(type = DesensitizeType.EMAIL)
private String email;
// 身份证脱敏
@Column(typeHandler = DesensitizeTypeHandler.class)
@Desensitize(type = DesensitizeType.ID_CARD)
private String idCard;
}代码生成器
public class CodeGenerator {
public static void main(String[] args) {
Generator generator = Generator.create(
// 数据源配置
new JdbcMySQLDataSource(
"jdbc:mysql://localhost:3306/mydb",
"root", "password"
)
);
// 生成配置
GlobalConfig config = generator.getGlobalConfig();
config.setBasePackage("com.example");
config.setSourceDir(System.getProperty("user.dir") + "/src/main/java");
config.setMapperXmlPath(System.getProperty("user.dir") + "/src/main/resources/mapper");
config.setEntityWithLombok(true);
config.setEntityJdk8Time(true);
// 执行生成
generator.generate();
}
}迁移检查清单
相关文章: