大家好,我是小悟。
一、MyBatis-Flex 介绍
MyBatis-Flex 是一个基于 MyBatis 的增强框架,它提供了比传统 MyBatis Plus 更加强大和灵活的功能特性。以下是其主要特点:
1. 核心特性
- 轻量级设计:框架非常轻量,依赖少,启动速度快
- 功能强大:提供丰富的查询API,支持多表关联查询、分页查询等
- 灵活的查询方式:支持 QueryWrapper、Lambda 表达式等多种查询方式
- 多数据库支持:兼容多种主流数据库(MySQL、PostgreSQL、Oracle等)
- 代码生成:内置高效的代码生成器
2. 优势亮点
- 无侵入性:对原有 MyBatis 几乎无侵入,迁移成本低
- 性能优越:查询性能经过优化,比传统 MyBatis 更高效
- 注解丰富:提供丰富的注解支持,简化配置
- 动态SQL:强大的动态 SQL 构建能力
- 多租户支持:内置多租户方案,开箱即用
二、SpringBoot 整合 MyBatis-Flex 详细步骤
步骤1:创建 SpringBoot 项目并添加依赖
<!-- pom.xml -->
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis-Flex SpringBoot Starter -->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.8.6</version>
</dependency>
<!-- 数据库驱动 (以MySQL为例) -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- Lombok (可选) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 代码生成器 (可选) -->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-codegen</artifactId>
<version>1.8.6</version>
<scope>provided</scope>
</dependency>
</dependencies>
步骤2:配置 application.yml
# application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis_flex_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
mybatis-flex:
# 配置 Mapper 扫描路径
mapper-locations: classpath*:/mapper/**/*Mapper.xml
# 全局配置
configuration:
# 下划线转驼峰
map-underscore-to-camel-case: true
# 日志实现
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 多数据源配置(可选)
datasource:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/master_db
username: root
password: 123456
slave:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/slave_db
username: root
password: 123456
步骤3:创建实体类
package com.example.demo.entity;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
@Data
@Accessors(chain = true)
@Table("tb_user") // 指定表名
public class User {
@Id(keyType = KeyType.Auto) // 主键,自动增长
private Long id;
private String username;
private String email;
private Integer age;
private Integer status;
private LocalDateTime createTime;
private LocalDateTime updateTime;
// 逻辑删除注解
@com.mybatisflex.annotation.Column(isLogicDelete = true)
private Boolean deleted;
}
步骤4:创建 Mapper 接口
package com.example.demo.mapper;
import com.mybatisflex.core.BaseMapper;
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 可以在此定义自定义的查询方法
// 复杂的查询建议使用 QueryWrapper 或 Db + Row
/**
* 自定义查询方法示例
*/
User selectByUsername(String username);
}
对应的 XML 映射文件(如果需要):
<!-- src/main/resources/mapper/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">
<mapper namespace="com.example.demo.mapper.UserMapper">
<select id="selectByUsername" resultType="com.example.demo.entity.User">
SELECT * FROM tb_user WHERE username = #{username}
</select>
</mapper>
步骤5:创建 Service 层
package com.example.demo.service;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.service.IService;
import com.example.demo.entity.User;
public interface UserService extends IService<User> {
User getByUsername(String username);
boolean updateEmailById(Long id, String email);
}
package com.example.demo.service.impl;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.service.impl.ServiceImpl;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Override
public User getByUsername(String username) {
QueryWrapper queryWrapper = QueryWrapper.create()
.select()
.from(User.class)
.where(User::getUsername).eq(username);
return mapper.selectOneByQuery(queryWrapper);
}
@Override
public boolean updateEmailById(Long id, String email) {
User user = new User();
user.setId(id);
user.setEmail(email);
return this.updateById(user);
}
}
步骤6:创建 Controller
package com.example.demo.controller;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
/**
* 根据ID查询用户
*/
@GetMapping("/{id}")
public User getById(@PathVariable Long id) {
return userService.getById(id);
}
/**
* 分页查询用户
*/
@GetMapping("/page")
public Page<User> page(@RequestParam(defaultValue = "1") int pageNumber,
@RequestParam(defaultValue = "10") int pageSize) {
QueryWrapper queryWrapper = QueryWrapper.create()
.select()
.from(User.class)
.where(User::getAge).ge(18)
.orderBy(User::getCreateTime, false);
return userService.page(new Page<>(pageNumber, pageSize), queryWrapper);
}
/**
* 条件查询
*/
@GetMapping("/list")
public List<User> list(@RequestParam(required = false) String username,
@RequestParam(required = false) Integer minAge) {
QueryWrapper queryWrapper = QueryWrapper.create()
.select()
.from(User.class);
if (username != null) {
queryWrapper.and(User::getUsername).like(username);
}
if (minAge != null) {
queryWrapper.and(User::getAge).ge(minAge);
}
return userService.list(queryWrapper);
}
/**
* 新增用户
*/
@PostMapping
public boolean save(@RequestBody User user) {
return userService.save(user);
}
/**
* 更新用户
*/
@PutMapping("/{id}")
public boolean update(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return userService.updateById(user);
}
/**
* 删除用户
*/
@DeleteMapping("/{id}")
public boolean delete(@PathVariable Long id) {
return userService.removeById(id);
}
}
步骤7:使用代码生成器(可选)
package com.example.demo;
import com.mybatisflex.codegen.Generator;
import com.mybatisflex.codegen.config.GlobalConfig;
import com.zaxxer.hikari.HikariDataSource;
public class CodeGenerator {
public static void main(String[] args) {
// 配置数据源
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mybatis_flex_db");
dataSource.setUsername("root");
dataSource.setPassword("123456");
// 创建配置内容
GlobalConfig globalConfig = new GlobalConfig();
// 设置根包
globalConfig.setBasePackage("com.example.demo");
// 设置表前缀和只生成哪些表
globalConfig.setTablePrefix("tb_");
globalConfig.setGenerateTable("tb_user", "tb_order", "tb_product");
// 设置生成实体类的路径
globalConfig.setEntitySourceDir("src/main/java/com/example/demo/entity");
// 设置生成Mapper类的路径
globalConfig.setMapperSourceDir("src/main/java/com/example/demo/mapper");
// 设置生成Service类的路径
globalConfig.setServiceSourceDir("src/main/java/com/example/demo/service");
// 设置生成ServiceImpl类的路径
globalConfig.setServiceImplSourceDir("src/main/java/com/example/demo/service/impl");
// 设置生成Controller类的路径
globalConfig.setControllerSourceDir("src/main/java/com/example/demo/controller");
// 通过 datasource 和 globalConfig 创建代码生成器
Generator generator = new Generator(dataSource, globalConfig);
// 生成代码
generator.generate();
}
}
步骤8:高级查询示例
package com.example.demo.service.impl;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.row.Row;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class AdvancedQueryService {
/**
* 复杂条件查询示例
*/
public void complexQuery() {
// 使用 QueryWrapper 构建复杂查询
QueryWrapper queryWrapper = QueryWrapper.create()
.select(User.ID, User.USERNAME, User.EMAIL)
.from(User.class)
.where(User.AGE.between(18, 60))
.and(User.STATUS.eq(1))
.and(User.USERNAME.like("张%"))
.orderBy(User.CREATE_TIME.desc())
.limit(10);
// 使用 Db 执行原生SQL
List<Row> rows = Db.selectListBySql(
"SELECT u.*, o.order_count FROM tb_user u " +
"LEFT JOIN (SELECT user_id, COUNT(*) as order_count FROM tb_order GROUP BY user_id) o " +
"ON u.id = o.user_id " +
"WHERE u.status = ?", 1);
}
/**
* 关联查询示例
*/
public void joinQuery() {
QueryWrapper query = QueryWrapper.create()
.select()
.from(User.class).as("u")
.leftJoin("tb_order").as("o").on("u.id = o.user_id")
.where("u.status = ?", 1);
}
}
步骤9:事务管理
package com.example.demo.service.impl;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class TransactionService {
@Autowired
private UserMapper userMapper;
/**
* 声明式事务管理
*/
@Transactional(rollbackFor = Exception.class)
public void transactionalOperation(User user1, User user2) {
// 插入第一个用户
userMapper.insert(user1);
// 模拟业务逻辑
if (user1.getAge() < 0) {
throw new RuntimeException("年龄不能为负数");
}
// 插入第二个用户
userMapper.insert(user2);
}
}
三、配置类示例
package com.example.demo.config;
import com.mybatisflex.core.audit.AuditManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Configuration
public class MyBatisFlexConfig {
private static final Logger logger = LoggerFactory.getLogger(MyBatisFlexConfig.class);
@PostConstruct
public void init() {
// 开启审计功能
AuditManager.setAuditEnable(true);
// 设置 SQL 审计收集器
AuditManager.setMessageCollector(auditMessage -> {
logger.info("执行 SQL: {}", auditMessage.getFullSql());
logger.info("执行参数: {}", auditMessage.getQueryParams());
logger.info("执行耗时: {}ms", auditMessage.getElapsedTime());
});
}
}
四、详细总结
1. 整合优势
- 简化开发:MyBatis-Flex 提供了丰富的 API,大大减少了样板代码
- 灵活查询:QueryWrapper 和 Lambda 表达式让查询条件构建更加灵活
- 性能优越:框架经过优化,执行效率高
- 易于扩展:良好的扩展性,可以方便地添加自定义功能
2. 使用建议
- 简单CRUD:直接使用 BaseMapper 和 IService 提供的基础方法
- 复杂查询:优先使用 QueryWrapper,复杂的关联查询可使用原生 SQL
- 分页查询:使用内置的 Page 类,支持多种数据库的分页语法
- 事务管理:使用 Spring 的 @Transactional 注解管理事务
3. 注意事项
- 实体类需要正确使用注解标记主键、表名等
- 多数据源配置时注意事务管理器的配置
- 逻辑删除字段需要在配置中指定
- 生产环境建议关闭 SQL 日志输出
4. 最佳实践
- 使用代码生成器提高开发效率
- 复杂业务逻辑在 Service 层处理
- 合理使用缓存提升性能
- 定期监控 SQL 执行效率
5. 常见问题解决
- 问题1:字段名与数据库列名映射不正确
- 解决:检查 @Column 注解或配置 map-underscore-to-camel-case
- 问题2:分页查询异常
- 解决:检查数据库方言配置,确保使用正确的分页语法
- 问题3:事务不回滚
- 解决:确保 @Transactional 注解正确使用,异常被正确捕获
MyBatis-Flex 作为一个现代化的 MyBatis 增强框架,在保持 MyBatis 灵活性的同时,提供了更多便捷的功能,特别适合需要复杂查询和高性能要求的项目。通过合理的配置和使用,可以大大提高开发效率和系统性能。
谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。
您的一键三连,是我更新的最大动力,谢谢
山水有相逢,来日皆可期,谢谢阅读,我们再会
我手中的金箍棒,上能通天,下能探海