大家好,我是小悟。
一、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 灵活性的同时,提供了更多便捷的功能,特别适合需要复杂查询和高性能要求的项目。通过合理的配置和使用,可以大大提高开发效率和系统性能。
谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。
您的一键三连,是我更新的最大动力,谢谢
山水有相逢,来日皆可期,谢谢阅读,我们再会
我手中的金箍棒,上能通天,下能探海