本篇文章內容主要包括:
MyBatis-Flex 介紹
MyBatis-Flex 是一個優雅的 MyBatis 增強框架,它非常輕量、同時擁有極高的性能與靈活性。我們可以輕松的使用 MybAIts-Flex 鏈接任何數據庫,其內置的 QueryWrApper^亮點 幫助我們極大的減少了 SQL 編寫的工作的同時,減少出錯的可能性。
總而言之,MyBatis-Flex 能夠極大地提高我們的開發效率和開發體驗,讓我們有更多的時間專注于自己的事情。
主要特點
- 輕量
除了 MyBatis,沒有任何第三方依賴輕依賴、沒有任何攔截器,其原理是通過 SqlProvider 的方式實現的輕實現。同時,在執行的過程中,沒有任何的 Sql 解析(Parse)輕運行。 這帶來了幾個好處:1、極高的性能;2、極易對代碼進行跟蹤和調試; 3、更高的把控性。
- 靈活
支持 Entity 的增刪改查、以及分頁查詢的同時,MyBatis-Flex 提供了 Db + Row^靈活 工具,可以無需實體類對數據庫進行增刪改查以及分頁查詢。 與此同時,MyBatis-Flex 內置的 QueryWrapper^靈活 可以輕易的幫助我們實現 多表查詢、鏈接查詢、子查詢 等等常見的 SQL 場景。
- 強大
支持任意關系型數據庫,還可以通過方言持續擴展,同時支持 多(復合)主鍵、邏輯刪除、樂觀鎖配置、數據脫敏、數據審計、 數據填充 等等功能。
與同類框架的對比
功能對比
|
功能或特點 |
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 的查詢單條數據的速度,大概是 MyBatis-Plus 的 5 ~ 10+ 倍。
- MyBatis-Flex 的查詢 10 條數據的速度,大概是 MyBatis-Plus 的 5~10 倍左右。
- Mybatis-Flex 的分頁查詢速度,大概是 Mybatis-Plus 的 5~10 倍左右。
- Mybatis-Flex 的數據更新速度,大概是 Mybatis-Plus 的 5~10+ 倍。
測試代碼:
https://gitee.com/mybatis-flex/mybatis-benchmark
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 |
星瑞格數據庫 |
基本使用
下面的演示案例代碼,基于MyBatis-Flex的代碼生成器進行實現。
創建數據表
創建數據表user_order,建表腳本如下:
DROP TABLE IF EXISTS `user_order`;
CREATE TABLE `user_order`
(
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID;【必須保留自增ID,不要將一些有隨機特性的字段值設計為主鍵,例如order_id,會導致innodb內部page分裂和大量隨機I/O,性能下降】int 大約21億左右,超過會報錯。bigint 大約9千億左右。',
`user_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用戶姓名;',
`user_id` varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用戶編號;',
`user_mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用戶電話;使用varchar(20)存儲手機號,不要使用整型。手機號不會做數學計算、涉及到區號或者國家代號,可能出現+-()、支持模糊查詢,例如:like“135%”',
`sku` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品編號',
`sku_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品名稱',
`order_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '訂單ID',
`quantity` int(11) NOT NULL DEFAULT 1 COMMENT '商品數量;整形定義中不顯示規定顯示長度,比如使用 INT,而不使用 INT(4)',
`unit_price` decimal(10, 2) NOT NULL COMMENT '商品價格;小數類型為 decimal,禁止使用 float、double',
`discount_amount` decimal(10, 2) NOT NULL COMMENT '折扣金額;',
`tax` decimal(4, 2) NOT NULL COMMENT '費率金額;',
`total_amount` decimal(10, 2) NOT NULL COMMENT '支付金額;(商品的總金額 - 折扣) * (1 - 費率)',
`order_date` datetime NOT NULL COMMENT '訂單日期;timestamp的時間范圍在1970-01-01 00:00:01到2038-01-01 00:00:00之間',
`order_status` tinyint(1) NOT NULL COMMENT '訂單狀態;0 創建、1完成、2掉單、3關單 【不要使用 enum 要使用 tinyint 替代。0-80 范圍,都可以使用 tinyint】',
`is_delete` tinyint(1) NOT NULL DEFAULT 0 COMMENT '邏輯刪單;0未刪除,1已刪除 【表達是否概念的字段必須使用is_】',
`uuid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '唯一索引;分布式下全局唯一,用于binlog 同步 ES 方便使用',
`ipv4` int(10) UNSIGNED NOT NULL DEFAULT 2130706433 COMMENT '設備地址;存儲IPV4地址,通過MySQL 函數轉換,.NET_ntoa、inet_aton 示例;SELECT INET_ATON(‘209.207.224.40′); 3520061480 SELECT INET_NTOA(3520061480); 209.207.224.40所有字段定義為NOT NULL,并設置默認值,因為null值的字段會導致每一行都占用額外存儲空間\n數據遷移容易出錯,在聚合函數計算結果偏差(如count結果不準)并且null的列使索引/索引統計/值比較都更加復雜,MySQL內部需要進行特殊處理,表中有較多空字段的時候,數據庫性能下降嚴重。開發中null只能采用is null或is not null檢索,而不能采用=、in、<、<>、!=、not in這些操作符號。如:where name!=’abc’,如果存在name為null值的記錄,查詢結果就不會包含name為null值的記錄',
`ipv6` varbinary(16) NOT NULL COMMENT '設備地址;存儲IPV6地址,VARBINARY(16) 插入:INET6_ATON('2001:0db8:85a3:0000:0000:8a2e:0370:7334') 查詢:SELECT INET6_NTOA(ip_address) ',
`ext_data` json NOT NULL COMMENT '擴展數據;記錄下單時用戶的設備環境等信息(核心業務字段,要單獨拆表)。【select user_name, ext_data, ext_data->>'$.device', ext_data->>'$.device.machine' from `user_order`;】',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uq_orderid` (`order_id`) USING BTREE,
UNIQUE INDEX `uq_uuid` (`uuid`) USING BTREE,
INDEX `idx_order_date` (`order_date`) USING BTREE,
INDEX `idx_sku_unit_price_total_amount` (`sku`, `unit_price`, `total_amount`) USING BTREE
);
創建Spring Boot項目
項目工程結構如下,在pomx.xml中添加相關依賴。
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.6.5</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.6.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-codegen</artifactId>
<version>1.6.5</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
項目配置
在配置文件application.yml中配置數據源等。
# 數據源配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/ballcat
username: root
password: root_123
在項目啟動類上添加@MapperScan 配置掃描的文件夾:
@SpringBootApplication
@MapperScan("com.xxkfz.simplememory.mapper")
public class XxkfzMybatisFlexApplication {
public static void main(String[] args) {
SpringApplication.run(XxkfzMybatisFlexApplication.class, args);
}
}
經過上面的步驟,一個基于Mybatis-Flex的簡單Spring Boot項目創建并配置完成了。
下面我們將使用Mybatis-Flex代碼生成器,生成基于表user-order的基本操作代碼。
配置代碼生成器
運行CodegenMain.JAVA main方法即可,即可在路徑:com/xxkfz/simplememory/下面生成相應的文件。
import com.mybatisflex.codegen.Generator;
import com.mybatisflex.codegen.config.ColumnConfig;
import com.mybatisflex.codegen.config.GlobalConfig;
import com.mybatisflex.core.service.IService;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.zaxxer.hikari.HikariDataSource;
/**
* @author 公眾號: SimpleMemory
* @version 1.0.0
* @ClassName Codegen.java
* @Description 代碼生成器
* @createTime 2023年09月21日 18:12:00
*/
public class CodegenMain {
public static void main(String[] args) {
//數據源配置
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/ballcat?characterEncoding=utf-8");
dataSource.setUsername("xxkfz");
dataSource.setPassword("xxkfz");
//創建配置內容,兩種風格都可以。
GlobalConfig globalConfig = createGlobalConfig();
//GlobalConfig globalConfig = createGlobalConfigUseStyle2();
//通過 datasource 和 globalConfig 創建代碼生成器
Generator generator = new Generator(dataSource, globalConfig);
//生成代碼
generator.generate();
}
/**
* GlobalConfig 基本配置
*
* @return
*/
public static GlobalConfig createGlobalConfig() {
//創建配置內容
GlobalConfig globalConfig = new GlobalConfig();
//設置根包
globalConfig.setBasePackage("com.xxkfz.simplememory");
//設置表前綴和只生成哪些表
globalConfig.setGenerateTable("user_order");
//設置生成 entity 并啟用 Lombok
globalConfig.setEntityGenerateEnable(true);
globalConfig.setEntityWithLombok(true);
//設置生成 controller
globalConfig.setControllerGenerateEnable(true);
//設置生成 service
globalConfig.setServiceGenerateEnable(true);
//設置生成 serviceImpl
globalConfig.setServiceImplGenerateEnable(true);
//設置生成 mapper
globalConfig.setMapperGenerateEnable(true);
//設置生成 mapperXml
globalConfig.setMapperXmlGenerateEnable(true);
globalConfig.getControllerConfig().setClassPrefix("").setClassSuffix("Controller").setRestStyle(true);
globalConfig.getServiceConfig().setClassPrefix("").setClassSuffix("Service").setSuperClass(IService.class).setOverwriteEnable(true);
globalConfig.getServiceImplConfig().setClassPrefix("").setClassSuffix("ServiceImpl").setSuperClass(ServiceImpl.class).setOverwriteEnable(true);
globalConfig.getMapperXmlConfig().setFilePrefix("/com/xxkfz/simplememory/").setFileSuffix("Mapper").setOverwriteEnable(true);
//可以單獨配置某個列
ColumnConfig columnConfig = new ColumnConfig();
columnConfig.setColumnName("tenant_id");
columnConfig.setLarge(true);
columnConfig.setVersion(true);
globalConfig.setColumnConfig("tb_account", columnConfig);
return globalConfig;
}
}
生成的代碼結構如下:
啟動項目測試
代碼生成后,我們直接主啟動類
XxkfzMybatisFlexApplication,即可啟動項目。
啟動成功后,訪問UserOrderController 中分頁查詢中的page方法:
http://127.0.0.1:8080/userOrder/page
其他操作QueryWrapper的使用
查詢表中user_name等于公眾號Simplememory的user_id、order_id列
QueryWrapper queryWrapper = QueryWrapper.create()
.select(USER_ORDER.USER_ID, USER_ORDER.ORDER_ID)
.where(USER_ORDER.USER_NAME
.eq("公眾號Simplememory"));
List<UserOrder> userOrders = userOrderMapper.selectListByQuery(queryWrapper);
System.out.println(userOrders);
在上面的例子中, USER_ORDER 為 MyBatis-Flex 通過 APT 自動生成的,無需手動編碼,只需通過靜態導入即可!
關于其他的用法可以進入:
https://mybatis-flex.com/zh/base/add-delete-update.html
Mybatis-Flex官方文檔: https://mybatis-flex.com/
最后,關于上面的代碼工程已上傳到Gitee:
https://gitee.com/xxkfz/xxkfz-mybatis-flex.git






