SpringBoot中MyBatis-Flex的集成和使用
一、MyBatis-Flex 是什么
MyBatis-Flex是一个基于MyBatis的数据访问框架,专门为Flex应用程序而设计的。它提供了一种灵活而高效的方式来处理Flex应用程序中的数据访问,可以轻松地连接到各种数据源,并提供了一些方便的工具和功能,包括对象关系映射(ORM)、动态查询、分页、事务处理等等。它的主要目的是简化数据访问的过程,使得开发人员可以更加专注于业务逻辑的开发,而不是一些琐碎的数据访问细节。
总而言之,MyBatis-Flex 能够极大地提高我们的开发效率和开发体验,让我们有更多的时间专注于自己的事情。
官方文档:MyBatis Flex官方网站
二、特征
1、轻量型
- 轻依赖:除了 MyBatis,没有任何第三方依赖轻依赖、没有任何拦截器
- 轻实现:原理是通过 SqlProvider 的方式实现
- 轻运行:没有任何的 Sql 解析,带来了这么几个好处:1、极高的性能;2、方便对代码进行跟踪和调试; 3、更高的把控性
2、使用灵活
- 支持 Entity 的增删改查、以及分页查询
- MyBatis-Flex 提供了 Db + Row^灵活 工具,可以无需实体类对数据库进行增删改查以及分页查询
- MyBatis-Flex 内置的 QueryWrapper^灵活 可以轻易的帮助我们实现多表查询、子查询和链接查询等常见的 SQL 查询场景
3、功能强大
- 支持任意关系型数据库,还可以通过方言持续扩展
- 支持多主键,逻辑删除、数据脱敏、数据填充和乐观锁配置等
三、MyBatis Flex的使用
1、创建数据库表
创建sql如下:
CREATE TABLE IF NOT EXISTS `tb_account`
(
`id` INTEGER PRIMARY KEY auto_increment,
`user_name` VARCHAR(100),
`age` INTEGER,
`birthday` DATETIME
);
INSERT INTO tb_account(id, user_name, age, birthday)
VALUES (1, '张三', 18, '2020-01-11'),
(2, '李四', 19, '2021-03-21');
2、创建 Spring Boot 项目,添加 依赖
可以使用 Spring Initializer 快速初始化一个 Spring Boot 工程。
需要添加的 Maven 主要依赖示例:
pom.xml配置如下:
<dependencies>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<!-- for test only -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3、对 Spring Boot 项目进行配置
在 application.yml 中配置数据源:
# DataSource Config
spring:
datasource:
url: jdbc:mysql://localhost:3306/flex_test
username: root
password: 12345678
在 Spring Boot 启动类中添加 @MapperScan
注解,扫描 Mapper 文件夹:
@SpringBootApplication
@MapperScan("com.mybatisflex.test.mapper")
public class MybatisFlexTestApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisFlexTestApplication.class, args);
}
}
4、编写实体类和 Mapper 接口
这里使用了 Lombok 注解来简化代码,类代码如下:
@Data
@Table("tb_account")
public class Account {
@Id(keyType = KeyType.Auto)
private Long id;
private String userName;
private Integer age;
private Date birthday;
}
- 使用
@Table("tb_account")
设置实体类与表名的映射关系 - 使用
@Id(keyType = KeyType.Auto)
标识主键为自增
Mapper 接口继承 BaseMapper 接口:
public interface AccountMapper extends BaseMapper<Account> {
}
这部分也可以使用 MyBatis-Flex 的代码生成器来生,功能非常强大的。详情进入:代码生成器章节 了解。
5、开始使用
添加测试类,进行功能测试:
import static com.mybatisflex.test.entity.table.AccountTableDef.ACCOUNT;
@SpringBootTest
class MybatisFlexTestApplicationTests {
@Autowired
private AccountMapper accountMapper;
@Test
void contextLoads() {
QueryWrapper queryWrapper = QueryWrapper.create()
.select()
.where(ACCOUNT.AGE.eq(18));
Account account = accountMapper.selectOneByQuery(queryWrapper);
System.out.println(account);
}
}
控制台输出:
Account(id=1, userName=张三, age=18, birthday=Sat Jan 11 00:00:00 CST 2020)
以上的 示例 中, ACCOUNT
为 MyBatis-Flex 通过 APT 自动生成,只需通过静态导入即可,无需手动编码。
点击查看更多APT文档 APT 文档。
若觉得 APT 使用不习惯,也可以使用代码生成器来生成。点击 代码生成器文档 了解。
四、同类框架「功能」对比
MyBatis-Flex 主要是和 MyBatis-Plus
与 Fluent-MyBatis
对比,内容来源其官网、git 或者 网络文章,若有错误欢迎纠正。
- MyBatis-Plus:老牌的 MyBatis 增强框架,开源于 2016 年。
- Fluent-MyBatis:阿里云开发的 MyBatis 增强框架(来自于阿里云·云效产品团队)
功能对比:
功能或特点 | MyBatis-Flex | MyBatis-Plus | Fluent-MyBatis |
---|---|---|---|
对 entity 的基本增删改查 | ✅ | ✅ | ✅ |
分页查询 | ✅ | ✅ | ✅ |
分页查询之总量缓存 | ✅ | ✅ | ❌ |
分页查询无 SQL 解析设计(更轻量,及更高性能) | ✅ | ❌ | ✅ |
多表查询: from 多张表 | ✅ | ❌ | ❌ |
多表查询: left join、inner join 等等 | ✅ | ❌ | ✅ |
多表查询: union,union all | ✅ | ❌ | ✅ |
单主键配置 | ✅ | ✅ | ✅ |
多种 id 生成策略 | ✅ | ✅ | ✅ |
支持多主键、复合主键 | ✅ | ❌ | ❌ |
字段的 typeHandler 配置 | ✅ | ✅ | ✅ |
除了 MyBatis,无其他第三方依赖(更轻量) | ✅ | ❌ | ❌ |
QueryWrapper 是否支持在微服务项目下进行 RPC 传输 | ✅ | ❌ | 未知 |
逻辑删除 | ✅ | ✅ | ✅ |
乐观锁 | ✅ | ✅ | ✅ |
SQL 审计 | ✅ | ❌ | ❌ |
数据填充 | ✅ | ✅ | ✅ |
数据脱敏 | ✅ | ✔️ (收费) | ❌ |
字段权限 | ✅ | ✔️ (收费) | ❌ |
字段加密 | ✅ | ✔️ (收费) | ❌ |
字典回写 | ✅ | ✔️ (收费) | ❌ |
Db + Row | ✅ | ❌ | ❌ |
Entity 监听 | ✅ | ❌ | ❌ |
多数据源支持 | ✅ | 借助其他框架或收费 | ❌ |
多数据源是否支持 Spring 的事务管理,比如 @Transactional 和 TransactionTemplate 等 | ✅ | ❌ | ❌ |
多数据源是否支持 "非Spring" 项目 | ✅ | ❌ | ❌ |
多租户 | ✅ | ✅ | ❌ |
动态表名 | ✅ | ✅ | ❌ |
动态 Schema | ✅ | ❌ | ❌ |
以上内容来自第三方相关产品的官方文档或第三方平台,若有错误,欢迎纠正。
五、同类框架「性能」对比
本文主要是展示了 MyBatis-Flex 和 Mybaits-Plus 的「性能」对比。Mybaits-Plus 是一个非常优秀 Mybaits 增强框架, 其开源于 2016 年,有很多的成功案例。
测试方法:
使用 h2 数据库,在初始化的时候分别为 mybatis-flex 和 mybatis-plus 创建两个不同的数据库, 但是完全一样的数据结构、数据内容和数据量(每个库 2w 条数据)。
开始之前先进行预热,之后通过打印时间戳的方式进行对比,谁消耗的时间越少,则性能越高(每次测试 10 轮)。
1、测试单条数据查询
MyBatis-Flex 的代码如下:
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.where(FLEX_ACCOUNT.ID.ge(100)
.or(FLEX_ACCOUNT.USER_NAME.eq("admin" + ThreadLocalRandom.current().nextInt(10000))));
mapper.selectOneByQuery(queryWrapper);
MyBatis-Plus 的代码如下:
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.ge("id", 100);
queryWrapper.or();
queryWrapper.eq("user_name", "admin" + ThreadLocalRandom.current().nextInt(10000));
queryWrapper.last("limit 1");
mapper.selectOne(queryWrapper);
10 轮的测试结果:
---------------
>>>>>>>testFlexSelectOne:134
>>>>>>>testPlusSelectOneWithLambda:989
>>>>>>>testPlusSelectOne:830
---------------
>>>>>>>testFlexSelectOne:75
>>>>>>>testPlusSelectOneWithLambda:732
>>>>>>>testPlusSelectOne:795
---------------
>>>>>>>testFlexSelectOne:65
>>>>>>>testPlusSelectOneWithLambda:938
>>>>>>>testPlusSelectOne:714
---------------
>>>>>>>testFlexSelectOne:105
>>>>>>>testPlusSelectOneWithLambda:740
>>>>>>>testPlusSelectOne:669
---------------
>>>>>>>testFlexSelectOne:57
>>>>>>>testPlusSelectOneWithLambda:691
>>>>>>>testPlusSelectOne:773
---------------
>>>>>>>testFlexSelectOne:65
>>>>>>>testPlusSelectOneWithLambda:693
>>>>>>>testPlusSelectOne:695
---------------
>>>>>>>testFlexSelectOne:56
>>>>>>>testPlusSelectOneWithLambda:754
>>>>>>>testPlusSelectOne:665
---------------
>>>>>>>testFlexSelectOne:56
>>>>>>>testPlusSelectOneWithLambda:714
>>>>>>>testPlusSelectOne:717
---------------
>>>>>>>testFlexSelectOne:57
>>>>>>>testPlusSelectOneWithLambda:696
>>>>>>>testPlusSelectOne:671
---------------
>>>>>>>testFlexSelectOne:59
>>>>>>>testPlusSelectOneWithLambda:739
>>>>>>>testPlusSelectOne:659
测试结论
MyBatis-Flex 的查询单条数据的速度,大概是 MyBatis-Plus 的 5 ~ 10+ 倍。
2、测试列表(List)数据查询
要求返回的数据为 10 条数据。
MyBatis-Flex 的代码如下:
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.where(FLEX_ACCOUNT.ID.ge(100).or(FLEX_ACCOUNT.USER_NAME
.eq("admin" + ThreadLocalRandom.current().nextInt(10000))))
.limit(10);
mapper.selectListByQuery(queryWrapper);
MyBatis-Plus 的代码如下:
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.ge("id", 100);
queryWrapper.or();
queryWrapper.eq("user_name", "admin" + ThreadLocalRandom.current().nextInt(10000));
queryWrapper.last("limit 10");
mapper.selectList(queryWrapper);
10 轮的测试结果:
---------------
>>>>>>>testFlexSelectTop10:90
>>>>>>>testPlusSelectTop10WithLambda:743
>>>>>>>testPlusSelectTop10:678
---------------
>>>>>>>testFlexSelectTop10:85
>>>>>>>testPlusSelectTop10WithLambda:692
>>>>>>>testPlusSelectTop10:684
---------------
>>>>>>>testFlexSelectTop10:84
>>>>>>>testPlusSelectTop10WithLambda:692
>>>>>>>testPlusSelectTop10:670
---------------
>>>>>>>testFlexSelectTop10:85
>>>>>>>testPlusSelectTop10WithLambda:737
>>>>>>>testPlusSelectTop10:667
---------------
>>>>>>>testFlexSelectTop10:85
>>>>>>>testPlusSelectTop10WithLambda:691
>>>>>>>testPlusSelectTop10:684
---------------
>>>>>>>testFlexSelectTop10:97
>>>>>>>testPlusSelectTop10WithLambda:760
>>>>>>>testPlusSelectTop10:666
---------------
>>>>>>>testFlexSelectTop10:80
>>>>>>>testPlusSelectTop10WithLambda:673
>>>>>>>testPlusSelectTop10:637
---------------
>>>>>>>testFlexSelectTop10:81
>>>>>>>testPlusSelectTop10WithLambda:653
>>>>>>>testPlusSelectTop10:639
---------------
>>>>>>>testFlexSelectTop10:82
>>>>>>>testPlusSelectTop10WithLambda:659
>>>>>>>testPlusSelectTop10:636
---------------
>>>>>>>testFlexSelectTop10:81
>>>>>>>testPlusSelectTop10WithLambda:654
>>>>>>>testPlusSelectTop10:656
测试结论
MyBatis-Flex 的查询 10 条数据的速度,大概是 MyBatis-Plus 的 5~10 倍左右。
3、分页查询
MyBatis-Flex 的代码如下:
QueryWrapper queryWrapper = new QueryWrapper()
.where(FLEX_ACCOUNT.ID.ge(100));
mapper.paginate(page, pageSize, 20000, queryWrapper);
MyBatis-Plus 的代码如下:
LambdaQueryWrapper<PlusAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.ge(PlusAccount::getId, 100);
queryWrapper.eq(PlusAccount::getEmail, "michael@gmail.com");
Page<PlusAccount> p = Page.of(page, pageSize, 20000, false);
mapper.selectPage(p, queryWrapper);
10 轮的测试结果:
---------------
>>>>>>>testFlexPaginate:90
>>>>>>>testPlusPaginate:671
---------------
>>>>>>>testFlexPaginate:78
>>>>>>>testPlusPaginate:643
---------------
>>>>>>>testFlexPaginate:80
>>>>>>>testPlusPaginate:638
---------------
>>>>>>>testFlexPaginate:79
>>>>>>>testPlusPaginate:613
---------------
>>>>>>>testFlexPaginate:75
>>>>>>>testPlusPaginate:627
---------------
>>>>>>>testFlexPaginate:72
>>>>>>>testPlusPaginate:606
---------------
>>>>>>>testFlexPaginate:69
>>>>>>>testPlusPaginate:585
---------------
>>>>>>>testFlexPaginate:70
>>>>>>>testPlusPaginate:589
---------------
>>>>>>>testFlexPaginate:69
>>>>>>>testPlusPaginate:586
---------------
>>>>>>>testFlexPaginate:68
>>>>>>>testPlusPaginate:585
测试结论
Mybatis-Flex 的分页查询速度,大概是 Mybatis-Plus 的 5~10 倍左右。
4、数据更新
Mybatis-Flex 的代码如下:
FlexAccount flexAccount = new FlexAccount();
flexAccount.setUserName("testInsert" + i);
flexAccount.setNickname("testInsert" + i);
flexAccount.addOption("key1", "value1");
flexAccount.addOption("key2", "value2");
flexAccount.addOption("key3", "value3");
flexAccount.addOption("key4", "value4");
flexAccount.addOption("key5", "value5");
QueryWrapper queryWrapper = QueryWrapper.create()
.where(FLEX_ACCOUNT.ID.ge(9200))
.and(FLEX_ACCOUNT.ID.le(9300))
.and(FLEX_ACCOUNT.USER_NAME.like("admin"))
.and(FLEX_ACCOUNT.NICKNAME.like("admin"));
mapper.updateByQuery(flexAccount, queryWrapper);
Mybatis-Plus 的代码如下:
PlusAccount plusAccount = new PlusAccount();
plusAccount.setUserName("testInsert" + i);
plusAccount.setNickname("testInsert" + i);
plusAccount.addOption("key1", "value1");
plusAccount.addOption("key2", "value2");
plusAccount.addOption("key3", "value3");
plusAccount.addOption("key4", "value4");
plusAccount.addOption("key5", "value5");
LambdaUpdateWrapper<PlusAccount> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.ge(PlusAccount::getId, 9000);
updateWrapper.le(PlusAccount::getId, 9100);
updateWrapper.like(PlusAccount::getUserName, "admin");
updateWrapper.like(PlusAccount::getNickname, "admin");
mapper.update(plusAccount, lambdaUpdateWrapper);
10 轮的测试结果:
---------------
>>>>>>>testFlexUpdate:58
>>>>>>>testPlusUpdate:524
---------------
>>>>>>>testFlexUpdate:51
>>>>>>>testPlusUpdate:503
---------------
>>>>>>>testFlexUpdate:49
>>>>>>>testPlusUpdate:490
---------------
>>>>>>>testFlexUpdate:45
>>>>>>>testPlusUpdate:472
---------------
>>>>>>>testFlexUpdate:48
>>>>>>>testPlusUpdate:470
---------------
>>>>>>>testFlexUpdate:44
>>>>>>>testPlusUpdate:460
---------------
>>>>>>>testFlexUpdate:43
>>>>>>>testPlusUpdate:459
---------------
>>>>>>>testFlexUpdate:44
>>>>>>>testPlusUpdate:461
---------------
>>>>>>>testFlexUpdate:40
>>>>>>>testPlusUpdate:444
---------------
>>>>>>>testFlexUpdate:41
>>>>>>>testPlusUpdate:444
测试结论
Mybatis-Flex 的数据更新速度,大概是 Mybatis-Plus 的 5~10+ 倍。
总之性能测试结果:
不论是MyBatis-Flex 单条查询分页查询还是数据更新,速度均是 MyBatis-Plus 的 5~10 倍左右!!!
六、MyBatis-Flex 支持的数据库
MyBatis-Flex 支持的数据库类型,如下表格所示,我们还可以通过自定义方言的方式,持续添加更多的数据库支持。
数据库 | 描述 |
---|---|
mysql | MySQL 数据库 |
mariadb | MariaDB 数据库 |
oracle | Oracle11g 及以下数据库 |
oracle12c | Oracle12c 及以上数据库 |
db2 | DB2 数据库 |
H2 | H2 数据库 |
hsql | HSQL 数据库 |
sqlite | SQLite 数据库 |
postgresql | PostgreSQL 数据库 |
sqlserver2005 | SQLServer2005 数据库 |
sqlserver | SQLServer 数据库 |
dm | 达梦数据库 |
xugu | 虚谷数据库 |
kingbasees | 人大金仓数据库 |
phoenix | Phoenix HBase 数据库 |
gauss | Gauss 数据库 |
clickhouse | ClickHouse 数据库 |
gbase | 南大通用(华库)数据库 |
gbase-8s | 南大通用数据库 GBase 8s |
oscar | 神通数据库 |
sybase | Sybase ASE 数据库 |
OceanBase | OceanBase 数据库 |
Firebird | Firebird 数据库 |
derby | Derby 数据库 |
highgo | 瀚高数据库 |
cubrid | CUBRID 数据库 |
goldilocks | GOLDILOCKS 数据库 |
csiidb | CSIIDB 数据库 |
hana | SAP_HANA 数据库 |
impala | Impala 数据库 |
vertica | Vertica 数据库 |
xcloud | 行云数据库 |
redshift | 亚马逊 redshift 数据库 |
openGauss | 华为 openGauss 数据库 |
TDengine | TDengine 数据库 |
informix | Informix 数据库 |
greenplum | Greenplum 数据库 |
uxdb | 优炫数据库 |
Doris | Doris数据库 |
Hive SQL | Hive 数据库 |
lealone | Lealone 数据库 |
sinodb | 星瑞格数据库 |