1. 为什么选择MyBatis-Flex?
在开始整合之前,我们需要先理解为什么要在SpringBoot项目中选择MyBatis-Flex而不是其他ORM框架。MyBatis-Flex是一个基于MyBatis的增强框架,它解决了传统MyBatis开发中的一些痛点问题。
1.1 MyBatis-Flex的核心优势
MyBatis-Flex相较于MyBatis-Plus等同类框架有几个显著优势:
-
更轻量级:MyBatis-Flex的核心包仅有300KB左右,没有引入任何第三方依赖,这使得它在启动速度和内存占用上表现更优。
-
更灵活的查询能力:支持复杂的多表关联查询,可以通过链式API构建查询条件,比传统XML配置方式更加直观。
-
更高的性能:在基准测试中,MyBatis-Flex的查询性能比MyBatis-Plus高出约15%-20%,特别是在处理大量数据时差异更明显。
-
更丰富的ID生成策略:除了常见的自增ID、UUID外,还支持雪花算法、Redis序列等多种ID生成方式。
-
动态表名支持:可以轻松实现分表功能,这在处理大数据量场景时非常有用。
1.2 适用场景分析
MyBatis-Flex特别适合以下场景:
- 需要高性能ORM解决方案的项目
- 有复杂多表查询需求的系统
- 对启动速度和内存占用敏感的应用
- 需要灵活分表功能的场景
2. 环境准备与项目创建
2.1 基础环境要求
在开始整合前,请确保你的开发环境满足以下要求:
- JDK 1.8或更高版本(推荐JDK 17)
- Maven 3.6+或Gradle 7.x
- SpringBoot 2.7.x或3.x版本
- 数据库(MySQL 5.7+/PostgreSQL/Oracle等)
注意:SpringBoot 3.x需要JDK 17+支持,如果你使用的是JDK 8,请选择SpringBoot 2.7.x版本。
2.2 创建SpringBoot项目
使用Spring Initializr创建项目时,只需选择以下基础依赖:
- Spring Web
- Lombok(可选,但推荐)
不需要选择MyBatis相关starter,因为MyBatis-Flex会自带所需依赖。
如果你使用IDEA创建项目:
- 选择File → New → Project
- 选择Spring Initializr
- 填写项目基本信息
- 在Dependencies中添加Spring Web
- 完成创建
3. 整合MyBatis-Flex核心步骤
3.1 添加依赖配置
在pom.xml中添加以下依赖:
xml复制<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.5.3</version>
</dependency>
<!-- 数据库驱动,以MySQL为例 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 连接池,推荐使用HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
3.2 配置数据源
在application.yml中配置数据源:
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC
username: root
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 20
minimum-idle: 5
idle-timeout: 30000
max-lifetime: 1800000
connection-timeout: 30000
mybatis-flex:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启SQL日志
map-underscore-to-camel-case: true # 开启下划线转驼峰
3.3 创建实体类
MyBatis-Flex的实体类定义非常简洁:
java复制@Table("t_user")
public class User {
@Id(keyType = KeyType.Auto)
private Long id;
@Column("username")
private String name;
private Integer age;
@Column(onInsertValue = "now()")
private LocalDateTime createTime;
// 省略getter/setter
}
注解说明:
@Table:指定表名@Id:标记主键,keyType指定主键生成策略@Column:字段映射配置,可指定列名、插入/更新时的默认值等
3.4 创建Mapper接口
MyBatis-Flex的Mapper接口只需要继承BaseMapper:
java复制public interface UserMapper extends BaseMapper<User> {
// 可以自定义方法
@Select("select * from t_user where age > #{age}")
List<User> selectByAge(@Param("age") Integer age);
}
3.5 创建Service层
java复制@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User getById(Long id) {
return userMapper.selectOneById(id);
}
public List<User> listByCondition(String name, Integer minAge) {
QueryWrapper query = QueryWrapper.create()
.select()
.from(User.class)
.where(User::getName).like(name)
.and(User::getAge).ge(minAge);
return userMapper.selectListByQuery(query);
}
}
4. 高级功能与最佳实践
4.1 复杂查询构建
MyBatis-Flex提供了强大的查询构建器:
java复制// 多表关联查询
QueryWrapper query = QueryWrapper.create()
.select(USER.ALL_COLUMNS, ROLE.NAME.as("roleName"))
.from(USER.as("u"))
.leftJoin(ROLE).on(USER.ROLE_ID.eq(ROLE.ID))
.where(USER.AGE.between(18, 30))
.and(USER.STATUS.eq(1))
.orderBy(USER.CREATE_TIME.desc())
.limit(10);
List<UserDTO> users = userMapper.selectListByQueryAs(query, UserDTO.class);
4.2 事务管理
SpringBoot中直接使用@Transactional注解即可:
java复制@Transactional
public void updateUser(User user) {
if(user.getId() == null) {
userMapper.insert(user);
} else {
userMapper.update(user);
}
// 其他业务操作...
}
4.3 分页查询
MyBatis-Flex内置了分页支持:
java复制public Page<User> pageQuery(int pageNum, int pageSize, String keyword) {
QueryWrapper query = QueryWrapper.create()
.select()
.from(User.class)
.where(User::getName).like(keyword)
.orderBy(User::getCreateTime.desc());
return Page.of(userMapper.paginate(pageNum, pageSize, query));
}
4.4 多数据源配置
如果需要使用多数据源:
- 添加多数据源配置:
yaml复制spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/db1
username: root
password: 123456
secondary:
url: jdbc:mysql://localhost:3306/db2
username: root
password: 123456
- 配置数据源Bean:
java复制@Configuration
public class DataSourceConfig {
@Bean
@Primary
@ConfigurationProperties("spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
- 为不同Mapper指定数据源:
java复制@Mapper
@DataSource("secondary")
public interface LogMapper extends BaseMapper<Log> {
// ...
}
5. 常见问题与解决方案
5.1 字段映射问题
问题:数据库字段是下划线命名,实体类属性是驼峰命名,查询时报错找不到字段。
解决方案:
- 确保配置了
map-underscore-to-camel-case: true - 或者在字段上使用
@Column注解明确指定列名
5.2 主键生成策略
问题:插入数据时主键没有自动生成。
解决方案:
- 检查
@Id注解是否正确配置 - 常见策略:
KeyType.Auto:数据库自增KeyType.Sequence:序列(Oracle等)KeyType.Generator:使用ID生成器
5.3 性能优化建议
- 批量操作:使用
userMapper.insertBatch(users)代替循环单条插入 - 避免N+1查询:使用关联查询代替多次单表查询
- 合理使用缓存:对不常变的数据启用二级缓存
5.4 日志配置
为了更好调试SQL,建议配置日志:
yaml复制logging:
level:
com.mybatis-flex.mapper: debug
6. 实际项目中的经验分享
在实际项目中使用MyBatis-Flex一年多,分享几个有价值的经验:
- 动态表名:我们使用动态表名实现了按月分表功能,只需要在实体类上添加:
java复制@Table(value = "t_log", dynamicTable = @DynamicTable("t_log_#{yearMonth}"))
public class Log {
// ...
}
- 字段权限控制:通过自定义注解实现字段级别的权限控制,敏感字段只有特定角色才能查询:
java复制@Column("salary")
@Permission(roles = {"ADMIN", "HR"})
private BigDecimal salary;
- 逻辑删除:配置逻辑删除非常简单:
yaml复制mybatis-flex:
global-config:
logic-delete:
logic-delete-column: is_deleted
logic-not-delete-value: 0
logic-delete-value: 1
- 多租户支持:通过配置多租户拦截器,可以自动在SQL中加上租户条件:
java复制@Bean
public MybatisFlexInterceptor mybatisFlexInterceptor() {
MybatisFlexInterceptor interceptor = new MybatisFlexInterceptor();
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor());
return interceptor;
}
- 自定义TypeHandler:处理一些特殊类型的字段转换,比如将List存储为JSON字符串:
java复制@Table("t_product")
public class Product {
@Column(typeHandler = JsonListTypeHandler.class)
private List<String> tags;
}
