MyBatis-Flex 完全学习指南 - 从入门到精通
一个优雅的 MyBatis 增强框架,让数据库操作变得简单高效
一、什么是 MyBatis-Flex?
1.1 简介
MyBatis-Flex 是一个优雅的 MyBatis 增强框架,它非常轻量、同时拥有极高的性能与灵活性。我们可以轻松的使用 MyBatis-Flex 连接任何数据库,其内置的 QueryWrapper 帮助我们极大的减少了 SQL 编写的工作,同时减少出错的可能性。
1.2 核心特性
┌─────────────────────────────────────────────────────────────┐
│ MyBatis-Flex 核心特性 │
├─────────────────────────────────────────────────────────────┤
│ 🪶 轻量 │
│ • 除 MyBatis 外无任何第三方依赖 │
│ • 无拦截器,通过 SqlProvider 实现 │
│ • 执行过程无 SQL 解析,性能极高 │
├─────────────────────────────────────────────────────────────┤
│ 🔧 灵活 │
│ • 支持 Entity 增删改查 + 分页 │
│ • 提供 Db + Row 工具,无需实体类操作 │
│ • QueryWrapper 支持多表查询、关联查询、子查询 │
├─────────────────────────────────────────────────────────────┤
│ 💪 强大 │
│ • 支持任意关系型数据库,可扩展方言 │
│ • 多主键、逻辑删除、乐观锁、数据脱敏 │
│ • 数据审计、数据填充等高级功能 │
└─────────────────────────────────────────────────────────────┘二、快速开始
2.1 环境准备
JDK: 1.8 或更高版本
Maven: 3.6+ 或 Gradle 7+
数据库: MySQL、PostgreSQL、Oracle 等任意关系型数据库
2.2 创建 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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>mybatis-flex-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mybatis-flex.version>1.8.0</mybatis-flex.version>
</properties>
<dependencies>
<!-- MyBatis-Flex 核心依赖 -->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>${mybatis-flex.version}</version>
</dependency>
<!-- 数据库驱动 - 以 MySQL 为例 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.20</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.9</version>
</dependency>
</dependencies>
</project>2.3 配置文件
mybatis-flex.properties:
# 数据源配置
dataSource.type=com.alibaba.druid.pool.DruidDataSource
dataSource.driver-class-name=com.mysql.cj.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
dataSource.username=root
dataSource.password=your_password
# MyBatis-Flex 配置
mybatis-flex.mapper-locations=classpath*:mapper/**/*.xml
mybatis-flex.type-aliases-package=com.example.entity或者使用 Java 配置类:
import com.alibaba.druid.pool.DruidDataSource;
import com.mybatisflex.core.MybatisFlexBootstrap;
import javax.sql.DataSource;
public class MyBatisConfig {
public static DataSource createDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf-8");
dataSource.setUsername("root");
dataSource.setPassword("your_password");
dataSource.setInitialSize(5);
dataSource.setMaxActive(20);
return dataSource;
}
public static void init() {
MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance();
bootstrap.setDataSource(createDataSource());
bootstrap.addMapper(UserMapper.class);
bootstrap.start();
}
}三、实体类与 Mapper
3.1 创建实体类
User.java:
import com.mybatisflex.annotation.*;
import java.util.Date;
@Table("tb_user") // 映射数据库表名
public class User {
@Id(keyType = KeyType.Auto) // 主键,自增
private Long id;
@Column("user_name") // 指定列名
private String userName;
private String email;
private Integer age;
@Column(isLogicDelete = true) // 逻辑删除字段
private Boolean isDeleted;
@Column(onInsertValue = "now()") // 插入时自动填充
private Date createTime;
@Column(onInsertValue = "now()", onUpdateValue = "now()") // 插入和更新时自动填充
private Date updateTime;
// Getters and Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUserName() { return userName; }
public void setUserName(String userName) { this.userName = userName; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public Boolean getIsDeleted() { return isDeleted; }
public void setIsDeleted(Boolean isDeleted) { this.isDeleted = isDeleted; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
@Override
public String toString() {
return "User{id=" + id + ", userName='" + userName + "', email='" + email + "', age=" + age + "}";
}
}3.2 创建 Mapper 接口
UserMapper.java:
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserMapper extends BaseMapper<User> {
// 自定义 SQL 方法
List<User> selectByAgeGreaterThan(@Param("age") Integer age);
}对应的 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">
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectByAgeGreaterThan" resultType="com.example.entity.User">
SELECT * FROM tb_user WHERE age > #{age} AND is_deleted = 0
</select>
</mapper>四、CRUD 操作实战
4.1 插入数据
import com.mybatisflex.core.query.QueryWrapper;
public class UserService {
private UserMapper userMapper;
// 插入单条记录
public void insertUser() {
User user = new User();
user.setUserName("张三");
user.setEmail("zhangsan@example.com");
user.setAge(25);
int rows = userMapper.insert(user);
System.out.println("插入成功,影响行数:" + rows);
System.out.println("生成的主键 ID:" + user.getId());
}
// 批量插入
public void batchInsert() {
List<User> users = Arrays.asList(
createUser("张三", "zs@example.com", 25),
createUser("李四", "ls@example.com", 30),
createUser("王五", "ww@example.com", 28)
);
int rows = userMapper.insertBatch(users);
System.out.println("批量插入成功,影响行数:" + rows);
}
private User createUser(String name, String email, Integer age) {
User user = new User();
user.setUserName(name);
user.setEmail(email);
user.setAge(age);
return user;
}
}4.2 查询数据
public class UserQueryService {
private UserMapper userMapper;
// 根据 ID 查询
public User getById(Long id) {
return userMapper.selectOneById(id);
}
// 条件查询 - 使用 QueryWrapper
public List<User> queryByCondition() {
QueryWrapper wrapper = QueryWrapper.create()
.from(User.class)
.where(User::getAge).ge(20) // age >= 20
.and(User::getUserName).like("张") // user_name like '%张%'
.orderBy(User::getCreateTime).desc();
return userMapper.selectListByQuery(wrapper);
}
// 多条件组合查询
public List<User> complexQuery(String keyword, Integer minAge, Integer maxAge) {
QueryWrapper wrapper = QueryWrapper.create()
.from(User.class)
.where(User::getIsDeleted).eq(false)
.and(wrapper -> {
wrapper.where(User::getUserName).like(keyword)
.or(User::getEmail).like(keyword);
})
.and(User::getAge).between(minAge, maxAge)
.orderBy(User::getAge).asc()
.orderBy(User::getCreateTime).desc();
return userMapper.selectListByQuery(wrapper);
}
// 分页查询
public Page<User> queryByPage(int pageNum, int pageSize) {
QueryWrapper wrapper = QueryWrapper.create()
.from(User.class)
.where(User::getIsDeleted).eq(false)
.orderBy(User::getCreateTime).desc();
Page<User> page = Page.of(pageNum, pageSize);
return userMapper.paginate(page, wrapper);
}
// 只查询部分字段
public List<Map<String, Object>> querySimple() {
QueryWrapper wrapper = QueryWrapper.create()
.select(User::getId, User::getUserName, User::getEmail)
.from(User.class)
.where(User::getAge).ge(18);
return userMapper.selectMapsByQuery(wrapper);
}
}4.3 更新数据
public class UserUpdateService {
private UserMapper userMapper;
// 根据 ID 更新
public void updateById(Long id) {
User user = new User();
user.setId(id);
user.setUserName("张三(已修改)");
user.setAge(26);
int rows = userMapper.update(user);
System.out.println("更新成功,影响行数:" + rows);
}
// 条件更新
public void updateByCondition() {
User user = new User();
user.setAge(30);
QueryWrapper wrapper = QueryWrapper.create()
.where(User::getUserName).like("测试");
int rows = userMapper.updateByQuery(user, wrapper);
System.out.println("条件更新成功,影响行数:" + rows);
}
// 使用 UpdateWrapper 进行更灵活的更新
public void updateWithWrapper() {
int rows = userMapper.updateByQuery(
UpdateWrapper.create()
.set(User::getAge, User::getAge + 1) // age = age + 1
.setRaw("update_time", "now()")
.where(User::getId).eq(1L)
);
System.out.println("更新成功,影响行数:" + rows);
}
}4.4 删除数据
public class UserDeleteService {
private UserMapper userMapper;
// 根据 ID 删除(逻辑删除)
public void deleteById(Long id) {
int rows = userMapper.deleteById(id);
System.out.println("删除成功,影响行数:" + rows);
}
// 批量删除
public void batchDelete(List<Long> ids) {
int rows = userMapper.deleteBatchByIds(ids);
System.out.println("批量删除成功,影响行数:" + rows);
}
// 条件删除
public void deleteByCondition() {
QueryWrapper wrapper = QueryWrapper.create()
.where(User::getAge).lt(18)
.and(User::getIsDeleted).eq(false);
int rows = userMapper.deleteByQuery(wrapper);
System.out.println("条件删除成功,影响行数:" + rows);
}
}五、高级特性
5.1 多表关联查询
// 定义关联查询结果实体
public class UserDetailVO {
private Long userId;
private String userName;
private String email;
private String departmentName; // 部门名称
private List<String> roleNames; // 角色列表
}
// 多表查询
public List<UserDetailVO> selectUserWithDepartment() {
QueryWrapper wrapper = QueryWrapper.create()
.select(
User::getId.as("userId"),
User::getUserName,
User::getEmail,
Department::getDeptName.as("departmentName")
)
.from(User.class)
.leftJoin(Department.class).on(User::getDeptId, Department::getId)
.where(User::getIsDeleted).eq(false);
return userMapper.selectListByQueryAs(wrapper, UserDetailVO.class);
}5.2 使用 Db + Row 工具
import com.mybatisflex.core.Db;
import com.mybatisflex.core.row.Row;
public class RowService {
// 使用 Row 进行增删改查(无需实体类)
public void rowExample() {
// 插入
Row row = new Row();
row.set("user_name", "赵六");
row.set("email", "zl@example.com");
row.set("age", 35);
Db.insert("tb_user", row);
// 查询
List<Row> rows = Db.selectListByQuery(
"tb_user",
QueryWrapper.create()
.where("age").ge(25)
.orderBy("create_time").desc()
);
for (Row r : rows) {
System.out.println("用户名:" + r.getString("user_name"));
System.out.println("邮箱:" + r.getString("email"));
}
// 更新
Row updateRow = new Row();
updateRow.set("age", 36);
Db.updateByQuery("tb_user", updateRow,
QueryWrapper.create().where("user_name").eq("赵六")
);
}
}5.3 乐观锁
// 实体类添加版本号字段
@Table("tb_account")
public class Account {
@Id
private Long id;
private String accountName;
private Double balance;
@Column(isVersion = true) // 乐观锁版本号
private Integer version;
}
// 使用乐观锁更新
public void transfer(Long fromId, Long toId, Double amount) {
Account fromAccount = accountMapper.selectOneById(fromId);
Account toAccount = accountMapper.selectOneById(toId);
fromAccount.setBalance(fromAccount.getBalance() - amount);
toAccount.setBalance(toAccount.getBalance() + amount);
// 乐观锁会自动处理版本号
int rows1 = accountMapper.update(fromAccount);
int rows2 = accountMapper.update(toAccount);
if (rows1 == 0 || rows2 == 0) {
throw new RuntimeException("转账失败,账户信息已被修改");
}
}5.4 数据填充
// 自动填充创建人和更新人
public class BaseEntity {
@Column(onInsertValue = "current_user()")
private String createBy;
@Column(onInsertValue = "now()", onUpdateValue = "now()")
private Date updateTime;
@Column(onUpdateValue = "current_user()")
private String updateBy;
}六、性能优化
6.1 缓存配置
// 开启二级缓存
@Table(value = "tb_user", cache = true)
public class User {
// ...
}
// 或者在配置文件中全局开启
mybatis-flex.configuration.cache-enabled=true6.2 SQL 打印
# 开发环境开启 SQL 打印
mybatis-flex.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl6.3 批量操作优化
// 大批量插入使用分批处理
public void largeBatchInsert(List<User> users) {
int batchSize = 500;
List<User> batch = new ArrayList<>();
for (int i = 0; i < users.size(); i++) {
batch.add(users.get(i));
if (batch.size() >= batchSize || i == users.size() - 1) {
userMapper.insertBatch(batch);
batch.clear();
}
}
}七、完整示例项目结构
mybatis-flex-demo/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ ├── MyBatisFlexApplication.java # 启动类
│ │ │ ├── config/
│ │ │ │ └── MyBatisConfig.java # 配置类
│ │ │ ├── entity/
│ │ │ │ ├── User.java # 用户实体
│ │ │ │ └── Department.java # 部门实体
│ │ │ ├── mapper/
│ │ │ │ ├── UserMapper.java # 用户 Mapper
│ │ │ │ └── DepartmentMapper.java # 部门 Mapper
│ │ │ ├── service/
│ │ │ │ ├── UserService.java # 用户服务
│ │ │ │ └── impl/
│ │ │ │ └── UserServiceImpl.java # 服务实现
│ │ │ └── vo/
│ │ │ └── UserDetailVO.java # 视图对象
│ │ └── resources/
│ │ ├── mybatis-flex.properties # 配置文件
│ │ └── mapper/
│ │ └── UserMapper.xml # XML 映射文件
│ └── test/
│ └── java/
│ └── com/
│ └── example/
│ └── UserMapperTest.java # 测试类
└── pom.xml # Maven 配置八、总结
8.1 MyBatis-Flex vs MyBatis-Plus
8.2 最佳实践
实体类设计:合理使用注解,避免过度设计
查询优化:复杂查询使用 QueryWrapper,简单查询使用 BaseMapper 方法
事务管理:Service 层使用
@Transactional注解分页查询:大数据量必须使用分页,避免内存溢出
日志配置:生产环境关闭 SQL 打印,开发环境开启
8.3 学习资源
结语
MyBatis-Flex 是一个值得尝试的 MyBatis 增强框架,它以轻量、灵活、高性能的特点,为 Java 开发者提供了更加优雅的数据库操作方式。无论是小型项目还是大型企业应用,MyBatis-Flex 都能很好地满足需求。
希望这篇学习笔记能帮助你快速上手 MyBatis-Flex,在实际项目中发挥其强大的功能!
文章作者:李立亮 发布时间:2026-03-09 分类:mybatis-flex 标签:MyBatis-Flex, Java, ORM, 数据库, 教程